Defer install() and configure_file() until libraries targets built

My CMakeLists.txt has two library targets. CPack needs to bundle the libraries and some other files that cannot be generated until the two library targets have been built. My understanding is that CMake cannot execute a function or macro as a custom target or command. Instead the generation and install() calls are placed in a separate .cmake file, along with “include(CPack)” at the end, and a ${CMAKE_COMMAND} is invoked with lots of parameters to copy all the standard variables into the new CMake instance. For some reason, even though the add_custom_target() is passed ALL and the DEPENDS passed the list of library targets, its COMMENT is never displayed. The ${CMAKE_BINARY_DIR}/CPackConfig.cmake is not generated.

Regardless, is there an easier way to do this? It is feeling like I am fighting the tool which is usually indicative of trying to do things the hard way. Any pointers would be greatly appreciated.

You could run a script that runs the macro/command, but you may also need to shuttle an unknown amount of information across the execution boundary for that to work reliably.

I’m afraid that without an example, it’s hard to suggest what might be wrong as what you describe sounds like it should work at least.

As for why the generation must wait, can you give a more concrete reason why they must exist first? It sounds odd that a library must exist first (an executable would make more sense to me) unless they’re something like Python modules you expect to import and actually execute. Any metadata about locations or the like should be known by CMake and available via file(GENERATE) with something like $<TARGET_FILE> expressions.

I have been wrestling with coming up with a solution and the root of the problem was likely a conceptual gap of understanding CMake. I now have a solution. If you could comment positively or negatively, that would be great.

CMake builds up a metadata representation of how to build the project, target order etc using keywords such as DEPENDS and commands like add_dependencies. Unfortunately that metadata is not accessible via get_target_property(). So I created my own custom target property TARGET_DEPENDENCIES and wrapped commands like add_custom_target and add_dependencies to also place the list of dependent targets in that new property and then call the wrapped command. I can then traverse the multiway tree of dependencies and ask each target for its OUTPUT_NAME and include directories for use in building the archive. Unfortunately, CMake does not set the OUTPUT_NAME when calling add_library(). It could set it to the name of the target as a default, but it does not. So, after calling add_library(), you need to call set_target_properties(). As an enhancement, I can wrap add_library() as well. Please let me know whether I finally “got” CMake and an appropriate solution. Thank you.

One side note - this is all to support building NuGet packages for which there is a CPack generator. I believe there is a gap where the NuGet dependency metadata is not being added to the NuGet package. This is from looking at the source code. I forked the CMake repository. If I can fix this, do you accept pull requests? I don’t think it will be a big change. Again, thank you.

Yeah, it could be set by default. Alas, something may be using “manually set OUTPUT_NAME” logic somehow, so it’d likely have to be a policy to do that :confused: . Making myproject_add_library sounds fine to me.

Yes, this sounds like a reasonable enhancement. I’m not sure of the mechanism, but some way to tell the NuGet CPack generator things like that sounds fine. I’d look at how the DPKG or RPM generators allow users to specify dependencies as guidance.