【问题标题】:Why doesn't CMake detect dependency on my generated file?为什么 CMake 不检测对我生成的文件的依赖?
【发布时间】:2016-12-16 18:40:10
【问题描述】:

我正在尝试使用自定义命令生成标题。每次重建时都应更新标头,以便包含它的源文件也将被重建。 (实际命令是脚本,这里是简化版。)

这是我的项目:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
set(test_SOURCES test.c)
include_directories("${CMAKE_BINARY_DIR}")

set(VERSION_H_PATH "${CMAKE_BINARY_DIR}/version.h")
message("VERSION_H_PATH: ${VERSION_H_PATH}")
add_custom_command(OUTPUT "${VERSION_H_PATH}" COMMAND "touch" "${VERSION_H_PATH}")
#add_custom_target(GENERATE COMMAND "touch" "${VERSION_H_PATH}")
add_executable(myprog ${test_SOURCES})
add_dependencies(myprog GENERATE)

test.c

#include <version.h>

int main()
{
    return 0;
}

现在的问题是,如上所述,CMakeList.txt 根本不会导致 version.h 被创建。只有在我从 add_custom_target 切换到 add_custom_command 之后它才会这样做。但是,如果我以某种方式更改文件,则下一个 make 不会重建项目。

看起来 CMake 无法识别 test.c 依赖于 version.h,尽管它明确地识别了 #include 它。我在这里做错了什么?

【问题讨论】:

    标签: cmake dependencies


    【解决方案1】:

    变化:

    add_custom_command(OUTPUT "${VERSION_H_PATH}" COMMAND "touch" "${VERSION_H_PATH}")
    #add_custom_target(GENERATE COMMAND "touch" "${VERSION_H_PATH}")
    add_executable(myprog ${test_SOURCES})
    add_dependencies(myprog GENERATE)
    

    进入:

    add_custom_command(OUTPUT "${VERSION_H_PATH}" COMMAND ${CMAKE_COMMAND} -E touch "${VERSION_H_PATH}") #More reliable touch, use cmake itself to touch the file
    add_custom_target(generate_version_h DEPENDS "${VERSION_H_PATH}")
    add_executable(myprog ${test_SOURCES})
    add_dependencies(myprog generate_version_h)
    

    见:

    1. CMake command line tool mode
    2. add_custom_target:

    依赖:

    在同一目录(CMakeLists.txt 文件)中使用 add_custom_command() 命令调用创建的自定义命令的参考文件和输出。 它们将在构建目标时更新。

    1. add_dependencies:

    使顶层依赖于其他顶层目标,以确保它们之前构建。顶级目标是由 add_executable()、add_library() 或 add_custom_target() 命令之一创建的目标(但不是由 CMake 生成的目标,例如 install)。

    顺便说一下,我不知道你的具体情况,但你可以考虑使用configure_file 来生成你的标题。

    【讨论】:

    • 所以你得到了赏金和赞成票,但我接受我自己的答案,因为它描述了我在自己的情况下必须做些什么来解决(愚蠢地制定的)问题。谢谢你指出我的错误。
    【解决方案2】:

    问题似乎是用于可执行目标的名称test是CMake保留的名称。请参阅政策CMP0037。为可执行文件使用不同的名称似乎与自定义目标一样工作:

    add_custom_target(GENERATE COMMAND "touch" "${VERSION_H_PATH}")
    add_executable(testexe ${test_SOURCES})
    add_dependencies(testexe GENERATE)
    

    【讨论】:

    • 似乎无法正常工作:您的变体无条件重建test.c.o。此外,如果我在我的版本中更改目标名称,症状仍然存在,所以这似乎不是原因。因此,我将编辑 OP 以避免使用保留的目标名称以防止进一步混淆。
    • @Ruslan 我不明白你在说什么:事实上,无条件(总是)构建 test.c.o 就是你要问的。您要求每次构建时都会触及 version.h,因此必须重新构建包含它的文件。你能澄清一下吗?
    • @Antonio 我现在觉得自己很愚蠢。现在当我测试它时,当我切换到(注释掉)add_custom_target 时,它甚至可以使用 OP 中的代码。我确实希望在每次构建时都运行该命令,但我不应该将命令简化那么多——它只应该有时更改标题。在我从构建目录中删除所有内容并重新运行cmake 之前,这无论如何都不起作用。甚至不知道现在该怎么处理这个问题......
    • @Ruslan 所以看来这毕竟是正确的答案,你应该接受它(也许回滚你的问题)。您还可以奖励其他有效的答案。顺便说一句,您使用的是哪个 cmake 版本?
    • @Antonio 不是:更改目标名称除了更改二进制名称之外不会产生任何结果。我的 cmake 版本是 2.8.12.2(Kubuntu 14.04 的默认版本)。
    【解决方案3】:

    每个自定义命令都需要一个驱动程序(取决于它的输出)。在您的情况下,最好的驱动程序是 test 可执行文件,这意味着您应该将生成的文件添加到可执行文件的源代码中:

    add_executable(test ${test_SOURCES} ${VERSION_H_PATH})
    

    【讨论】:

    • 如果我从命令行touch version.h 或在构建后删除version.h 并再次尝试make,它仍然不会重建test.c.o
    • @Ruslan 奇怪。它实际上是否包含正确的version.h 文件?这是一个很常见的名字,是不是取了一个不相关的名字?
    • 是的。我已经完成了echo asdfdsaf &gt; version.h; rm CMakeFiles/test.dir/test.c.o; rm test; make 并得到了预期的编译失败。但并非不删除二进制文件。
    【解决方案4】:

    好的,实际上这个问题从一开始就很糟糕。我不应该像我那样简化生成命令。但是我遇到的问题似乎已经通过删除构建目录的内容并重新运行cmake来解决。出于某种原因,对 CMakeLists.txt 的一些更改对于 cmake 来说并不容易理解。所以这里是CMakeLists.txt,它确实有效,并且没有太多简化的生成器命令:

    cmake_minimum_required(VERSION 2.8)
    set(test_SOURCES test.c)
    include_directories("${CMAKE_BINARY_DIR}")
    
    set(VERSION_H_PATH "${CMAKE_BINARY_DIR}/version.h")
    message("VERSION_H_PATH: ${VERSION_H_PATH}")
    add_custom_target(GENERATE COMMAND "bash" "-c" "[ -e ${VERSION_H_PATH} ] \\|\\| touch ${VERSION_H_PATH}")
    add_executable(myprog ${test_SOURCES})
    add_dependencies(myprog GENERATE)
    

    即使使用保留的test 目标而不是myprog,这似乎也有效。

    【讨论】:

    • 这解决了我的问题。我花了几个小时认为我做错了,并搜索了无数线程。创建一个新的build文件夹,CMake检测到生成的target对生成文件包含的头文件的依赖关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多