Answer
To make an object library rebuild when a header generated by add_custom_command changes, treat that header as a source of the object library (with the OBJECT keyword) and mark it as a header‑only file. This forces CMake to record the header as a prerequisite of each object file’s rule.
Why this works (likely explanation)
CMake’s dependency tracking only considers files that appear in a target’s source list. If the generated header is not listed, changes to its timestamp are ignored by the build system, even though the custom command runs first. Adding the header to the object library’s sources makes the build system see it as an input, so a newer timestamp triggers recompilation of the dependent object files.
Confirmed facts from CMake behavior
- Any file added via
target_sources( OBJECT …) becomes a dependency of the object files in .
- Setting the source file property
HEADER_FILE_ONLY ON prevents CMake from trying to compile the header as source code.
- The source file property
OBJECT_DEPENDS can also be used to list additional dependencies that trigger recompilation of object files.
- For multi‑configuration generators, place the generated header in a configuration‑specific location (e.g.,
$<CONFIG>/generated.h) or use a generator expression in the OUTPUT of add_custom_command so each config sees the correct file.
Steps to apply
- Declare the custom command that generates the header:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.h
COMMAND ${CMAKE_COMMAND} -E echo "// generated header" > ${CMAKE_CURRENT_BINARY_DIR}/generated.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/generator.in
COMMENT "Generating generated.h"
)
- Create (or reference) the object library:
add_library(myobj OBJECT src1.cpp src2.cpp)
- Add the generated header as an object‑library source and mark it header‑only:
target_sources(myobj OBJECT
${CMAKE_CURRENT_BINARY_DIR}/generated.h
)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/generated.h
PROPERTIES HEADER_FILE_ONLY OBJECT_DEPENDS ""
)
- If using a multi‑config generator, make the output path config‑aware:
add_custom_command(
OUTPUT $<CONFIG>/generated.h
COMMAND …
)
target_sources(myobj OBJECT $<CONFIG>/generated.h)
set_source_files_properties($<CONFIG>/generated.h
PROPERTIES HEADER_FILE_ONLY ON
)
- Optionally, ensure the custom command runs before compilation:
add_custom_target(gen_hdr DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated.h)
add_dependencies(myobj gen_hdr)
Verification
After touching the generator script or its dependencies, re‑run the build. The object file’s compilation command should appear again (check build timestamps or the build log). Inspect the generated build system (e.g., Makefile or ninja.build) to confirm that the generated header appears as a prerequisite of the object file’s rule.