Add way to get list of link-time static libraries in generator expression
It would be nice to have a generator expression similar to $<TARGET_RUNTIME_DLLS:tgt> that would get all of the static libraries a target depends on. Something like $<TARGET_LINKTIME_STATIC_LIBRARIES:tgt>. Ideally this could have a version/option that only contains targets that have a corresponding add_library in the CMake code, but anything is better than nothing.
I don't think a target property would suffice here because you don't necessarily know the whole tree of targets at the point where you add the binary.
EXAMPLE USE CASE
---------
I understand that object libraries do not support deep transitivity. #18682 (closed)
I also understand that, as of now, there isn't a good way to use --whole_archive, /WHOLEARCHIVE, -link-all, etc with deep transitivity. #16947 (closed)
This is inconvenient for large codebases (i.e. deep trees of compartmentalized targets) that use the static registration pattern in C++ and perhaps also rely on transitivity of __dllexport. When linking a static library, the linker excludes object files with unreferenced symbols, and hence will not pick up the object files containing solely these symbols. This makes porting a build system that uses such practices to CMake difficult.
The only reliable solution seems to be to keep an explicit list of symbols to be included in the final binary, either by hand, or by writing an automated tool that uses dumpbin or similar to dig through the symbols and pull out ones matching a particular pattern, referencing those in a header. Thankfully that can be done in CMake with a custom build command. This solution, in contrast to something like whole-archive, also keeps binaries small.
In order to facilitate implementing such an automated tool, it would be nice to have a generator expression similar to $<TARGET_RUNTIME_DLLS:tgt> that would get all of the static libraries a target depends on. Something like $<TARGET_LINKTIME_STATIC_LIBRARIES:tgt>. This could then be passed in the arguments to a custom command to generate a header that is included in the final application.
Such a build step is needed when building the binary because the included header needs to have exactly the symbols compiled into the binary. If it has the symbols from all the static libraries in the build system, the linker will generate missing symbol errors.
---------
In the meantime, I've ensured the target I need the libraries for is defined after all the targets it depends on, and fetch the static library deps recursively using interface target property. It's not ideal that it has to be defined last, but it works.