Define a pre-build command without creating a new target

I’ve made a minimal reproducible example: dummy.zip (1.0 KB)
The three behaviours I get are:

with add_custom_command(OUTPUT "${dummy_BINARY_DIR}/date.h" "foo"

output
====================[ Build | dummy | Debug ]===================================
/usr/bin/cmake --build /mnt/d/Users/Nemo/Desktop/dummy/cmake-build-debug --target dummy -- -j 12
Scanning dependencies of target dummy
[ 33%] Building C object CMakeFiles/dummy.dir/main.c.o
/mnt/d/Users/Nemo/Desktop/dummy/main.c:2:10: fatal error: date.h: No such file or directory
 #include "date.h"
          ^~~~~~~~
compilation terminated.
CMakeFiles/dummy.dir/build.make:88: recipe for target 'CMakeFiles/dummy.dir/main.c.o' failed
make[3]: *** [CMakeFiles/dummy.dir/main.c.o] Error 1
CMakeFiles/Makefile2:94: recipe for target 'CMakeFiles/dummy.dir/all' failed
make[2]: *** [CMakeFiles/dummy.dir/all] Error 2
CMakeFiles/Makefile2:101: recipe for target 'CMakeFiles/dummy.dir/rule' failed
make[1]: *** [CMakeFiles/dummy.dir/rule] Error 2
Makefile:137: recipe for target 'dummy' failed
make: *** [dummy] Error 2

with add_custom_command(OUTPUT "foo" "${dummy_BINARY_DIR}/date.h"

  • case 1: the header change doesn’t trigger a recompilation fixed by clearing the CMake cache
output
====================[ Build | dummy | Debug ]===================================
/usr/bin/cmake --build /mnt/d/Users/Nemo/Desktop/dummy/cmake-build-debug --target dummy -- -j 12
[ 33%] generating build date header
[100%] Built target dummy

Build finished
  • case 2: it works, but two “generating” messages are print, which is suspicious
output
====================[ Build | dummy | Debug ]===================================
/usr/bin/cmake --build /mnt/d/Users/Nemo/Desktop/dummy/cmake-build-debug --target dummy -- -j 12
[ 33%] generating build date header
Scanning dependencies of target dummy
[ 33%] generating build date header
[ 66%] Building C object CMakeFiles/dummy.dir/main.c.o
[100%] Linking C executable dummy
[100%] Built target dummy

Build finished

It implements the same concept, but he runs it at configure time, with execute_process(), so he doesn’t really have to handle dependencies.