先决条件更改后 Cmake 不重建依赖项
Cmake does not rebuild dependent after prerequisite changes
我有如下依赖图
a.txt <- prereq <- stamp <- dest
其中 prereq
和 dest
是目标,a.txt
和 stamp
是文件。我希望在 a.txt
更改时更新邮票。
为此,我有以下 CMakeLists.txt 文件:
cmake_minimum_required(VERSION 3.6)
project(sample)
# variable holding location of stamp and a.txt file
set(STAMP ${CMAKE_CURRENT_SOURCE_DIR}/stamp)
set(ATXT ${CMAKE_CURRENT_SOURCE_DIR}/a.txt)
add_custom_target(
prereq
DEPENDS ${ATXT}
)
add_custom_command(
OUTPUT ${STAMP}
COMMAND ${CMAKE_COMMAND} -E echo "Update stamp."
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP}
DEPENDS prereq
)
add_custom_target(dest ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/stamp)
最初,我有以下文件
$ ls
a.txt
CMakeLists.txt
在 运行第一次 cmake 和 make 之后,我们得到了预期的行为,
$ cmake .
$ make
[ 0%] Built target prereq
[100%] Generating stamp
Update stamp.
[100%] Built target dest
然而,在触摸 a.txt
之后,我希望 stamp
得到更新,但它没有。
$ touch a.txt
$ make
[ 0%] Built target prereq
[100%] Built target dest
这是 cmake 中的错误还是预期的行为?我们如何在每次 prereq
更改时强制 cmake 运行 触摸命令?
DEPENDS
在 add_custom_target()
和 add_custom_command()
调用中的行为不同。
只需移动 ATXT
作为您的 add_custom_command(OUTPUT ${STAMP} ...)
调用的依赖项应该可以解决问题,因为在 add_custom_target()
中命名非输出文件将不起作用。
见add_custom_command()
documentation:
DEPENDS
: Specify files on which the command depends. If any dependency is an OUTPUT
of another custom command in the same directory (CMakeLists.txt
file) CMake automatically brings the other custom command into the target in which this command is built. If DEPENDS
is not specified the command will run whenever the OUTPUT is missing.
见add_custom_target()
documentation:
DEPENDS
: Reference files and outputs of custom commands created with add_custom_command()
command calls in the same directory (CMakeLists.txt
file).
add_custom_target()
中的DEPENDS
参数仅用于确定target/custom调用依赖。
编辑:"Late Dependency Injection"
的备选方案
如果您在同一个 CMakeLists.txt
文件中,您可以 APPEND
依赖于先前的自定义命令 OUTPUT
:
add_custom_command(
OUTPUT ${STAMP}
COMMAND ${CMAKE_COMMAND} -E echo "Update stamp."
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP}
)
add_custom_target(dest ALL DEPENDS ${STAMP})
add_custom_command(
OUTPUT ${STAMP}
DEPENDS ${ATXT}
APPEND
)
您可以添加一些虚拟输出来为您的 prereq
目标提供自定义命令,但要重新触发 dest
的构建,您需要触摸一些输入或删除 dest
的输出(add_dependencies()
本身不会重新触发自定义目标,它只是确保一个在另一个之前被调用):
add_custom_command(
OUTPUT ATxtCheck
COMMAND ${CMAKE_COMMAND} -E remove ${STAMP}
COMMAND ${CMAKE_COMMAND} -E touch ATxtCheck
DEPENDS ${ATXT}
)
add_custom_target(prereq DEPENDS ATxtCheck)
add_custom_command(
OUTPUT ${STAMP}
COMMAND ${CMAKE_COMMAND} -E echo "Update stamp."
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP}
DEPENDS prereq
)
add_custom_target(dest ALL DEPENDS ${STAMP})
参考资料
- Why does CMake make a distinction between a "target" and a "command"?
- cmake: struggling with add_custom_command dependencies
我有如下依赖图
a.txt <- prereq <- stamp <- dest
其中 prereq
和 dest
是目标,a.txt
和 stamp
是文件。我希望在 a.txt
更改时更新邮票。
为此,我有以下 CMakeLists.txt 文件:
cmake_minimum_required(VERSION 3.6)
project(sample)
# variable holding location of stamp and a.txt file
set(STAMP ${CMAKE_CURRENT_SOURCE_DIR}/stamp)
set(ATXT ${CMAKE_CURRENT_SOURCE_DIR}/a.txt)
add_custom_target(
prereq
DEPENDS ${ATXT}
)
add_custom_command(
OUTPUT ${STAMP}
COMMAND ${CMAKE_COMMAND} -E echo "Update stamp."
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP}
DEPENDS prereq
)
add_custom_target(dest ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/stamp)
最初,我有以下文件
$ ls
a.txt
CMakeLists.txt
在 运行第一次 cmake 和 make 之后,我们得到了预期的行为,
$ cmake .
$ make
[ 0%] Built target prereq
[100%] Generating stamp
Update stamp.
[100%] Built target dest
然而,在触摸 a.txt
之后,我希望 stamp
得到更新,但它没有。
$ touch a.txt
$ make
[ 0%] Built target prereq
[100%] Built target dest
这是 cmake 中的错误还是预期的行为?我们如何在每次 prereq
更改时强制 cmake 运行 触摸命令?
DEPENDS
在 add_custom_target()
和 add_custom_command()
调用中的行为不同。
只需移动 ATXT
作为您的 add_custom_command(OUTPUT ${STAMP} ...)
调用的依赖项应该可以解决问题,因为在 add_custom_target()
中命名非输出文件将不起作用。
见add_custom_command()
documentation:
DEPENDS
: Specify files on which the command depends. If any dependency is anOUTPUT
of another custom command in the same directory (CMakeLists.txt
file) CMake automatically brings the other custom command into the target in which this command is built. IfDEPENDS
is not specified the command will run whenever the OUTPUT is missing.
见add_custom_target()
documentation:
DEPENDS
: Reference files and outputs of custom commands created withadd_custom_command()
command calls in the same directory (CMakeLists.txt
file).
add_custom_target()
中的DEPENDS
参数仅用于确定target/custom调用依赖。
编辑:"Late Dependency Injection"
的备选方案如果您在同一个
CMakeLists.txt
文件中,您可以APPEND
依赖于先前的自定义命令OUTPUT
:add_custom_command( OUTPUT ${STAMP} COMMAND ${CMAKE_COMMAND} -E echo "Update stamp." COMMAND ${CMAKE_COMMAND} -E touch ${STAMP} ) add_custom_target(dest ALL DEPENDS ${STAMP}) add_custom_command( OUTPUT ${STAMP} DEPENDS ${ATXT} APPEND )
您可以添加一些虚拟输出来为您的
prereq
目标提供自定义命令,但要重新触发dest
的构建,您需要触摸一些输入或删除dest
的输出(add_dependencies()
本身不会重新触发自定义目标,它只是确保一个在另一个之前被调用):add_custom_command( OUTPUT ATxtCheck COMMAND ${CMAKE_COMMAND} -E remove ${STAMP} COMMAND ${CMAKE_COMMAND} -E touch ATxtCheck DEPENDS ${ATXT} ) add_custom_target(prereq DEPENDS ATxtCheck) add_custom_command( OUTPUT ${STAMP} COMMAND ${CMAKE_COMMAND} -E echo "Update stamp." COMMAND ${CMAKE_COMMAND} -E touch ${STAMP} DEPENDS prereq ) add_custom_target(dest ALL DEPENDS ${STAMP})
参考资料
- Why does CMake make a distinction between a "target" and a "command"?
- cmake: struggling with add_custom_command dependencies