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 anOUTPUTof another custom command in the same directory (CMakeLists.txtfile) CMake automatically brings the other custom command into the target in which this command is built. IfDEPENDSis 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.txtfile).
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