Automatically detecting generated dependencies

Our project has multiple source files and multiple generated header files (in addition to non-generated header files if that matters). These source files variously depend on these generated header files. How can I get cmake to recognize that some of the header files referenced in a source file need to be generated from a another file without explicitly declaring any dependencies. I’m thinking of something like: "if cmake can’t find a referenced header file in the source tree, but is somehow declared in the CMakeLists.txt, to use that non-existent file as a dependency as if it existed somewhere.

You need to either add a dependency on the generated header from the library (add_library(mylib genheader.h)) if it is the only library that needs it (or is at a unique root of a dep graph needing it) or add_custom_target(genheader DEPENDS genheader.h) then add_dependencies(mylib genheader) for each library needing it).

I don’t think this can be implicit behavior; a missing header versus a generated header is not solvable at any moment when CMake is guaranteed to actually be running across all generators.

This is more than one header file and in fact, the number of header files can change if the source data for those headers change. I was hoping to have some automated way of creating and updating those header files and have their usage by source files automatically detected. To add more complication, these header files are used by multiple libraries most with a lot of sources and not all libraries use all the generated headers. I wonder if there’s a “next best thing” than explicitly detailing a libraries dependencies on these headers.

Each of those headers would have an add_custom_command. I’d attach a target to each (or maybe one target to all headers if that works out better):

add_custom_command(OUTPUT "${outdir}/genhdr1.h" DEPENDS hdr1.input COMMAND …)
add_custom_command(OUTPUT "${outdir}/genhdr2.h" DEPENDS hdr2.input COMMAND …)

if (target_per_header) # Decide which side is better for your use case.
  add_custom_target(genhdr1 DEPENDS "${outdir}/genhdr1.h")
  add_custom_target(genhdr2 DEPENDS "${outdir}/genhdr2.h")
  add_custom_target(genhdrs DEPENDS genhdr1 genhdr2)
else ()
  add_custom_target(genhdrs DEPENDS "${outdir}/genhdr1.h" "${outdir}/genhdr2.h")
endif ()

add_library(mylib …)
add_dependencies(mylib genhdrs) # Or each header target individually.

There’s no other way to reliably do what you want as far as I know. And as I said above, CMake would not be able to do this automatically. The headers generated are known at configure/generate time, but CMake can only look at source during the build which would mean shuttling all this data across and then somehow updating the build to add the link for the generated header. Not all generators support such a thing, so it would not be a solution anyways.

Hi Chris:

I am not sure, but are you perhaps looking for the GENERATED property?
That property is documented (with details about how dependencies are related to that property)
at https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html.

Alan

Thanks for help.

I am using add_custom_command to generate the headers. I believe that marks those files GENERATED. Is there any reason why this wouldn’t?

The headers are spread across many libraries and not every library will need every generated header. Two things I’m thinking of trying: Add the generated headers a dependencies of the top-level library; I’m hoping that will get them in the door so-to-speak and cmake might recognize these headers even though they don’t yet exist. I’m also thinking of generating the headers before running cmake or maybe before declaring the top-level library; I’m hoping that, not only will cmake definitely see the headers, but cmake will also respect the rules to generate them. When I have the time I will try these things.

I saw a topic reference this one and I thought I’d suggest some functionality for CMake that would be useful. We couldn’t go with CMake largely because of this problem and instead went with an in-house solution. We can declare virtual header files that the dependency scanner is aware of. These files are not guaranteed to exist during scanning and are not scanned themselves; nonetheless, the proper dependency is made between the source file and the various generated headers. It would be nice if CMake had such a capability for its dependency scanner.

1 Like

add_custom_command(DEPFILE) does exist, but it only works with Ninja. It may work with the Makefiles generators in the future, but I don’t know its status. The MR to overhaul Makefiles generator dependency scanning is here.