Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么CMake要区分“a”;“目标”;及;命令;?_Cmake - Fatal编程技术网

为什么CMake要区分“a”;“目标”;及;命令;?

为什么CMake要区分“a”;“目标”;及;命令;?,cmake,Cmake,在CMake语义中,“目标”和“命令”之间存在某种区别,这让我感到困惑。在Makefiles中,没有这种区别: targetname:dependency command i、 e.目标对应于生成的同名文件 在CMake中,有“添加自定义命令”和“添加自定义目标”等具有重叠功能的命令,甚至在官方文档中,语义也很混乱,即在第110页“添加自定义目标”下的“掌握CMake,第5版”中: DEPENDS参数设置自定义目标之间的依赖关系 和自定义命令 我的理解是,目标(生成的文件)有依赖项(其

在CMake语义中,“目标”和“命令”之间存在某种区别,这让我感到困惑。在Makefiles中,没有这种区别:

targetname:dependency
    command
i、 e.目标对应于生成的同名文件

在CMake中,有“添加自定义命令”和“添加自定义目标”等具有重叠功能的命令,甚至在官方文档中,语义也很混乱,即在第110页“添加自定义目标”下的“掌握CMake,第5版”中:

DEPENDS参数设置自定义目标之间的依赖关系 和自定义命令

我的理解是,目标(生成的文件)有依赖项(其他文件,生成或不生成),以及实际执行生成的命令。说目标依赖于命令是毫无意义的。更糟糕的是,有两种类型的“添加\自定义\命令”“将附加命令附加到现有目标,或将命令吐出到以太中

有人能解释一下为什么存在这种区别吗

目标 通常,目标由可执行文件或库组成,这些文件或库通过调用或定义,并且可以有多个集合

它们可以相互依赖,这对于像这样的目标来说仅仅意味着依赖的对象将在它们的依赖之后构建

但是,您也可以通过定义“自定义目标”。从文档中:

添加一个具有给定名称的目标,该目标执行给定命令。目标没有输出文件,即使命令尝试创建具有目标名称的文件,也始终认为该文件已过期。使用ADD_CUSTOM_命令生成具有依赖项的文件。默认情况下,任何内容都不依赖于自定义目标。使用“添加依赖项”向其他目标添加依赖项或从其他目标添加依赖项

因此,它们不同于“普通”目标,因为它们不表示将生成exe或lib的内容,但它们仍然受益于目标可以具有的所有属性,包括具有或作为依赖项。它们显示为可生成的目标(例如,
make MyCustomTarget
msbuild MyCustomTarget.vcxproj
)。构建它们时,只需调用为它们设置的命令。如果它们依赖于其他目标(普通或自定义),那么将首先构建这些目标


自定义命令 通过定义的自定义命令有很大的不同,因为它不是“可构建”对象,也不像目标那样具有可设置的属性-它不是在添加到CMakeLists.txt后可以再次显式引用的命名对象

它基本上是一个命令(或一组命令),在构建依赖目标之前将被调用。这就是“依赖”在这里的真正含义(至少我是这么看的)——它只是说,如果A依赖于B,那么B将在A被构建之前被构建/执行

自定义命令的依赖项可以使用
add\u custom\u命令(TARGET TARGET…
表单)显式设置,也可以通过创建包含通过
add\u custom\u命令(OUTPUT output1…
表单)生成的文件的目标隐式设置

在第一种情况下,每次构建
target
,都会首先执行自定义命令


在第二种情况下,它稍微复杂一些。如果自定义命令具有依赖于其输出文件的目标(而输出文件还不存在),则会在生成这些依赖对象之前调用它。当您这样做时(例如,
add_library(MyLib output1.h…)会隐式创建依赖项
其中
output1.h
是通过
add_custom_命令(OUTPUT output1.h…
)生成的文件

add_custom_命令添加一个可调用函数,该函数可以定义输出(使用输出和副产品参数)。它还可以具有在调用函数之前运行的依赖项

请注意,由于奇怪的文档(makefile示例非常误导),它不会执行您可能认为它会执行的操作。特别是,它对执行次数没有任何保证。例如,想象一下:

add_custom_command(OUTPUT /tmp/touched COMMAND echo touch COMMAND touch /tmp/touched)
add_custom_target(touched-one ALL DEPENDS /tmp/touched)
add_custom_target(touched-two ALL DEPENDS /tmp/touched)
“touch”将打印多少次?您不知道,因为它在任何地方都没有指定;make-j2可能会打印两次,但它取决于时间:

Scanning dependencies of target touched-two
Scanning dependencies of target touched-one
[ 50%] Generating touched
touch
[100%] Generating touched
touch
[100%] Built target touched-two
[100%] Built target touched-one
但忍者可能只会打印一次:

# rm -rf * && cmake -GNinja ../c ; cmake --build . -- -j 5
[1/1] Generating touched
touch
通常,您将执行一个add_custom_命令来执行一些工作,并定义一个输出,然后您将拥有一个add_custom_目标,该目标依赖于自定义命令的输出。任何想要输出的人都依赖于目标,这确实为您提供了所需的保证


警告:请看一个很好的例子,说明为什么构建跨平台metabuild工具非常困难。

感谢您尝试解释Fraser的混乱,但我试图理解为什么CMake开发人员首先会制造这种混乱。我希望有一个很好的理由,但我怀疑这只是另一个像a一样糟糕的设计决策Well caps fiasco.@DrewWagner好吧,我同意所有caps的问题,但我不能说我对命令与目标的关系有问题。也许我只是习惯了:-)我知道Kitware的人非常小心地保持向后兼容性,因此他们必须支持他们可能不喜欢的东西。这也会造成灰色区域,我猜新命令与现有命令的职责重叠。关于命令/目标设置的原始原理,你可能会e最好询问?自定义目标用于在完全虚构的工件上挂起自定义操作,而自定义命令用于在实际存在的工件上挂起一点自定义处理。一些示例:使用自定义目标在项目中创建一个处理某些资源或i18n文件的目标。使用自定义命令