【发布时间】:2021-02-20 21:10:37
【问题描述】:
一个非常简单的场景 - 我需要生成头文件,包含它,如果生成的头文件在 cmake 构建时更新,所有依赖的 cpp 单元也必须重新构建。
一个简化的例子:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/test.h
COMMAND ...
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test.in"
add_custom_target(test_target DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/test.h)
add_executable(test_exe
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
add_dependencies(test_exe test_target)
main.cpp 只是:
#include "test.h"
int main()
{
return 0;
}
当我进行完全重建时,一切都很好。但是当我更改test.in 时,只运行cmake.exe --build . --target all 只重新生成test.h,但不会重新编译main.cpp。但是当我再次(第二次)运行cmake.exe --build . --target all 时,main.cpp 被重新编译,test_exe 被重新链接。
我做错了什么?
附:如果我明确使用OBJECT_DEPENDS,则没有问题,重建工作正常,但文档说不再需要 - https://cmake.org/cmake/help/v3.20/prop_sf/OBJECT_DEPENDS.html
更新: 我使用 Windows 10、CMake 3.19.2 和 Ninja 1.10.2
解决方案: 使用项目目录中的构建目录,则没有问题。但是如果构建目录在我们的项目目录之外,那就有问题了。
【问题讨论】:
-
不相关,但是可以直接在
add_executable命令中添加目标,不需要add_dependencies。 -
我预见到有关使用
add_custom_target和add_dependencies的反应,因此决定使用它们。我尝试了所有可能的变体(没有显式依赖,使用静态库)。唯一有效的变体是设置OBJECT_DEPENDS,但 IMO 它已经过时且不方便。 -
add_dependencies只给出目标之间的ordering。要使自定义命令生成的标头上的可执行文件依赖,请将该标头添加到add_executable调用:add_executable(test_exe ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test.h)。 -
@Tsyvarev
test.h包含在main.cpp中。但是我试过了,还是不行。 -
可能需要使用什么 CMake 版本、平台和生成器。在您的示例中添加
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/test.in" ${CMAKE_CURRENT_SOURCE_DIR}/test.h以及cmake_minimum_required和project将在我的Windows 机器上重新编译main.cpp。使用 msbuild 和 Ninja 的 CMake 版本 3.18.2。您是否碰巧合并了多个 CMakeLists.txt 文件以尽量减少问题?