Getting all PUBLIC & INTERFACE definitions including from dependencies

Hi. I have stumbled upon an use case where I think this might come handy, but I am not sure if possible in current CMake.

My project specifies a target A which depends on targets B & C. For third party integration, I instruct users to specify the needed include, library paths and definitions.

This day I got bitten by not specifying all definitions which created an API/ABI inconsistency (Compiled A target used different struct size than the users integration).

To combat this, I was thinking of using INTERFACE_COMPILE_DEFINITIONS to query needed public defines for target A (and its dependencies), which I could then install as a config.h header or something similar for users to not require setting a list of defines manually.

Unfortunately the following property does not extend to dependencies. If either B or C targets add or remove certain configuration define then those aren’t reflected in A target property.

Is there a way to transitively get all PUBLIC and INTERFACE definitions of a certain target, which could then be “exported” to a config header file for consumption by a third party library integration?
Or better yet is there a preferred way of making your project/library easier to ingest by third party integrations?

You’ll need to use generator expressions to get this information. VTK does this for includes and compile definitions to pass along to the code which reads VTK headers and writes out wrapper code. See here for the way to get them written out to a file at least.

A couple of alternatives:

  • Set CMAKE_EXPORT_COMPILE_COMMANDS to true and check the actual compiler command lines contain the things you want in the generated JSON file.
  • Use CMake’s file API to export similar details as above.

I can’t offer much guidance on either method, but the above should at least give you a couple of starting points for your own investigations.

Thanks both for your prompt suggestions.
Ben’s solution is exactly what I have been looking for.

I’ve decided not to go with a single config.h file for defining those as in that case I’d have to make sure that its included before any other includes of library as well as dependent libraries.

I still used the technique to create an up to date text file of defines that are needed, which I then refer to in the README.

Thanks again both for your help!

Note that you’ll want to make a target which links to the targets you want to get the interface of. Asking the target directly gets its PRIVATE interfaces and usage requirements through its PRIVATE linked targets.