【问题标题】:cmake: struggling with add_custom_command dependenciescmake:与 add_custom_command 依赖关系苦苦挣扎
【发布时间】:2010-10-24 20:13:00
【问题描述】:

我试图让一个目录中的 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 只适用于文件依赖项,所以这似乎不是正确的解决方案。 (那你怎么有一个依赖于顶级目标的自定义命令呢?)

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

【问题讨论】:

    标签: cmake


    【解决方案1】:

    cmake 文档中关于 DEPENDS 参数的说明如下:

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

    因此,我认为您必须使用 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 ....)

    【讨论】:

    • 不幸的是,这个解决方案不起作用。 (我意识到在将近一年过去之后,回复可能是无望的。)据我所知, add_custom_command 的 DEPENDS 参数必须是文件级依赖项 - 尽管文档说目标级依赖项 in同一个目录 可以工作,事实上我在过去的 11 个月里尝试了许多不同的排列,但没有一个工作。也就是说,如果我在同一目录中定义自定义目标“foo”,然后说 DEPENDS“foo”,它会简单地报告“no rules to make target 'foo' ...”
    • @Talin 所以这似乎是一个错误,CMake bugtracker 是否报告了此问题?
    【解决方案2】:

    这是对您上述answers 之一的澄清。

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

    IMO,cmake 文档应该改为:

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

    这意味着如果您的所有目标都标记为EXCLUDE_FROM_ALL,并且您有创建新目标的add_custom_target 命令,并且您在没有指定目标的命令行中键入make,则添加了@ 的目标987654326@ 是构建的。但是,如果您在 make 命令行上明确地拼出它们,那么它们就会被构建。此外,您可以将 ALL 关键字指定给 add_custom_target 以强制将它们构建为 all 规则的一部分,我相信这意味着当 make 不带参数执行时。

    【讨论】:

    • 我同意。 “总是被建造”这句话并不是真的。
    【解决方案3】:

    尝试将以下命令添加到第二个目录:

    set_source_files_properties(${PROJECT_BINARY_DIR}/lib/core/libcore.bc PROPERTIES GENERATED TRUE)
    

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

    【讨论】:

      【解决方案4】:

      我不认为add_custom_target 可以满足我的需求。根据 cmake 文档,由 add_custom_target 创建的自定义目标总是被认为是过时的并且总是被构建的。

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

      这就是我想要做的事情:我有一个程序可以在给定源文件的情况下生成一个 .bc 文件(LLVM 位码)。这些源文件有很多,会创建很多 .bc 文件。

      第二个程序将所有 .bc 文件转换为单个 .obj(ELF 对象)文件。所以转换步骤是这样的:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-04
        • 2012-05-31
        • 2021-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多