【发布时间】:2024-01-04 16:02:02
【问题描述】:
我有一个多目录 CMake 项目,我在其中生成两个文件 b 和 c。然后我有一个需要c 的可执行文件d_target。
- 文件
b依赖于一些配置文件a - 文件
c依赖于文件b - 可执行目标
d_target需要c,这是一个生成的头文件。
我添加了两个add_custom_command() 调用来生成文件并添加了依赖项。
然后,我添加了两个 add_custom_target() 调用以使目标在整个多目录项目中可用。
file a > file b > b_target > file c > c_target > d_target
我第一次构建c_target,所有的依赖都被构建,文件c等于b和b等于a。
现在,当我更改“配置”a 并构建 d_target 时,d_target 不会重新构建。
当 CMake 的任何依赖项发生更改时,如何让 CMake 重建目标?
cmake_minimum_required(VERSION 3.15)
project(abcd)
# ./b/CMakeLists.txt
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/b
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/a > ${CMAKE_CURRENT_BINARY_DIR}/b
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/a)
add_custom_target(b_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/b)
# ./c/CMakeLists.txt
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/c
COMMAND cat ${CMAKE_CURRENT_BINARY_DIR}/b > ${CMAKE_CURRENT_BINARY_DIR}/c
DEPENDS b_target ${CMAKE_CURRENT_BINARY_DIR}/b)
add_custom_target(c_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/c)
# ./d/CMakeLists.txt
add_executable(d_target ${CMAKE_CURRENT_SOURCE_DIR}/d.cpp)
add_dependencies(d_target c_target)
# will not generate:
# add_dependencies(d_target c_target ${CMAKE_CURRENT_BINARY_DIR}/c)
在我的具体情况下,b 和 c 和 d 的命令在各自子目录的 CMakeLists.txt 中。
演示:
$ make d_target
[ 20%] Generating b
[ 20%] Built target b_target
[ 40%] Generating c
[ 60%] Built target c_target
[ 80%] Building CXX object CMakeFiles/d_target.dir/d.cpp.o
[100%] Linking CXX executable d_target
[100%] Built target d_target
$ touch ../a
$ make d_target
[ 20%] Generating b
[ 20%] Built target b_target
[ 40%] Generating c
[ 60%] Built target c_target
[100%] Built target d_target
当我尝试将c 文件添加到add_dependencies(d_target ...) 时,CMake 失败:
CMake Error at CMakeLists.txt:21 (add_dependencies):
The dependency target "/home/tom/tmp/abcd/build/c" of target
"d_target" does not exist.
【问题讨论】:
-
正如当前代码中所写,
b/CMakeLists.txt中的add_custom_command将在b的构建目录中创建b。但是c/CMakeLists.txt中的${CMAKE_CURRENT_BINARY_DIR}/b指的是c的构建目录中的b。所以你在不同的目录中有不同的b文件。 -
@Tsyvarev 感谢您的评论,我稍微澄清了这个例子,但这不是根本问题。
-
哦,您需要在
c/CMakeLists.txt中添加${CMAKE_CURRENT_BINARY_DIR}/b作为add_custom_command的依赖项。否则,如果文件b已更改,CMake(和 Make)不知道您要重建文件c。仅当目标是可执行文件或库(使用add_executable或add_library调用创建)时,将目标指定为依赖项会自动添加文件级依赖项。由于您的b_target是自定义目标,因此它不会添加文件级依赖项。另请参阅add_custom_target 的文档。 -
取决于文件,而不是目标。
-
"可执行目标 d_target 需要 c。" - 可执行目标
d_target是从单个源文件d.cpp创建的。 为什么编译/链接d_target需要文件c? 如何文件c影响d_target的编译或链接?