cmake:与add_custom_command依赖关系挣扎

时间:2010-10-24 20:13:00

标签: cmake

我正在尝试将add_custom_command在一个目录中生成的文件作为另一个目录中add_custom_command的依赖项。

在第一个目录(lib / core)中,我有一个如下所示的构建命令:

add_custom_command(
    OUTPUT libcore.bc
    COMMAND tartln -filetype=bc -link-as-library -o libcore.bc ${STDLIB_BC_FILES}
    DEPENDS ${STDLIB_BC_FILES} tartln
    COMMENT "Linking libcore.bc")

在第二个目录中,我有一个使用该命令输出的命令:

add_custom_command(OUTPUT ${OBJ_FILE}
    COMMAND tartln -disable-fp-elim -filetype=obj -o ${OBJ_FILE} ${BC_FILE}
        "${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
    MAIN_DEPENDENCY "${BC_FILE}" 
    DEPENDS "${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
    COMMENT "Linking Tart bitcode file ${BC_FILE}")

但是,当我尝试构建时,我收到以下错误:

make[3]: *** No rule to make target `lib/core/libcore.bc', needed by `test/stdlib/ReflectionTest.o'.  Stop.

我看到的一个奇怪的事情是,错误消息中的路径是相对路径,而不是绝对路径,尽管我知道$ {PROJECT_BINARY_DIR}是一个完整,正确的路径。我不知道这是一个问题,还是只是一种陌生的做法。

我还尝试在lib / core目录中为libcore库创建一个顶级目标:

add_custom_target(libcore DEPENDS libcore.bc libcore.deps)

然后在DEPENDS子句中使用它。奇怪的是,它是第一次执行干净构建时工作,但在任何后续构建时都会出错。在任何情况下,我的理解是DEPENDS仅适用于文件依赖,因此这似乎不是正确的解决方案。 (你如何拥有一个依赖于顶级目标的自定义命令?)

我也试过把绝对路径放到各处,没有效果。

4 个答案:

答案 0 :(得分:7)

cmake文档说明了以下有关DEPENDS参数的内容:

  

DEPENDS选项指定命令所依赖的文件。如果          任何依赖项都是另一个自定义命令的OUTPUT          目录(CMakeLists.txt文件)CMake自动带来另一个          自定义命令到构建此命令的目标中。如果          DEPENDS指定任何目标(由ADD_ *命令创建)a          创建目标级依赖项以确保构建目标          在使用此自定义命令的任何目标之前

因此我认为您必须使用add_custom_target定义目标并依赖于此。

add_custom_target的文档说:

  

使用DEPENDS参数列出的依赖项   可以引用用其创建的自定义命令的文件和输出   add_custom_command()在同一目录(CMakeLists.txt文件)中。

所以你必须使用add_custom_command和add_custom_target,如下所示:

  1. 在生成bc文件的第一个目录中,您可以

    add_custom_command(OUTPUT libcore.bc ... ) # just as in your question  add_custom_target (LibCoreBC DEPENDS libcore.bc)

  2. 在第二个目录中执行

    add_custom_command (OUT ${OBJ_FILE} DEPENDS LibCoreBC ....)

答案 1 :(得分:3)

这是一个非答案,但对上述answers之一的澄清。

  

根据cmake文档,add_custom_target创建的自定义目标始终被视为已过期且始终已构建。

IMO,cmake文件应该说:

  

add_custom_target创建的自定义目标始终被视为过期,并且始终构建,但仅在请求时

这意味着如果您的所有目标都标记为EXCLUDE_FROM_ALL,并且您有add_custom_target个命令可以创建新目标,并且您从命令行键入make而未指定目标,add_custom_target添加的目标已构建。但是如果你明确地将它们拼写在make命令行上,那么它们就是构建的。此外,您可以为ALL指定add_custom_target关键字,以强制将这些关键字构建为all规则的一部分,我相信这意味着在没有参数的情况下执行make

答案 2 :(得分:0)

我认为add_custom_target不适用于我想要的东西。根据cmake文档,add_custom_target创建的自定义目标始终被视为过时,并且始终构建。

问题在于我尝试从一个add_custom_command获取输出,并将其输入到另一个目录中的另一个add_custom_command的输入中。我只希望在原始源文件过期时发生这种情况 - 如果我使用add_custom_target,那么即使源文件没有改变,也总是会重建输出。鉴于有数百个这样的源文件,这将使构建非常慢。

这就是我要做的事情:我有一个程序,它在给定源文件的情况下生成.bc文件(LLVM bitcode)。有很多这些源文件,它们会创建大量的.bc文件。

第二个程序将所有.bc文件转换为单个.obj(ELF对象)文件。所以转换步骤如下所示:

   source file -> .bc     (via add_custom_command)
   .bc         -> .obj    (via add_custom_command)
   .obj        -> .exe    (via add_executable)

原始源代码文件位于不同的目录中,因为它们是类库 - 我不想将每个类库的所有代码放在同一目录中。

答案 3 :(得分:0)

尝试将以下命令添加到第二个目录: set_source_files_properties($ {PROJECT_BINARY_DIR} /lib/core/libcore.bc属性已生成TRUE)

我用此命令解决了我的问题。 相关链接:https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html