I have the following dependency diagram
a.txt <- prereq <- stamp <- dest
where prereq
and dest
are targets, and a.txt
and stamp
are files. I want stamp to be updated whenever a.txt
changes.
To achieve that, I have the following CMakeLists.txt file:
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)
Initially, I have the following files
$ ls
a.txt
CMakeLists.txt
After running cmake and make for the first time we get the expected behavior,
$ cmake .
$ make
[ 0%] Built target prereq
[100%] Generating stamp
Update stamp.
[100%] Built target dest
However, after touching a.txt
, I would expect stamp
to get updated, but it does not.
$ touch a.txt
$ make
[ 0%] Built target prereq
[100%] Built target dest
Is this a bug in cmake or is this the expected behavior? How can we force cmake to run the touch command every time prereq
changes?
DEPENDS
in add_custom_target()
and add_custom_command()
calls are behaving differently.
Just move ATXT
as dependency of your add_custom_command(OUTPUT ${STAMP} ...)
call should solve the problem, because naming non-output files in add_custom_target()
won't work.
See 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.
See 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).
The DEPENDS
parameter in add_custom_target()
is only meant to determine target/custom call dependencies.
Edit: Alternatives for "Late Dependency Injection"
If you are in the same CMakeLists.txt
file you can APPEND
dependencies to a previous custom command 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
)
You can add some dummy output to have a custom command for your prereq
target, but to retrigger the build of dest
you need to touch some of the inputs or remove the output of dest
(add_dependencies()
itself does not re-trigger a custom target, it just makes sure one is called before the other):
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})
References
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With