`install()`-ing a static library also requires installing an internal object library?

I have two directories, src and src/runtime, which each contain their own CMakeLists.txt. src contains my main target. runtime contains a large number of files which are (in a series of steps) transformed into .cpp files that export an array containing the bytes of the transformed resources.

Because these .cpp files are generated via add_custom_command, I cannot add them to my main target with target_sources. So instead, I add them to an OBJECT library and then link it to my main target with target_link_libraries in src.

This works well when I’m building my library as a shared library. But when I try to build it as a static library, the packaging system complains that I haven’t exported the internal OBJECT library. If I add it to the export set, then the generated imported target adds -lmy_proj_runtime to the linker lines of consuming projects, which is just wrong.

This is also a problem with 3rd-party dependencies that should be loaded via find_dependencies at Config time. It results in a linker line that reflects the names of the IMPORTED targets I created out of the variables the old CMake 2.8 libraries set.

What is the correct solution for this? Is there something about the CMake model I’m not understanding? Should I only link to these libraries via $<BUILD_INTERFACE:...>? Will that even work? It seems like a hack.

This is a gotcha when using object libraries. Instead of using target_link_libraries() to link to the object library, try the following:

add_library(runtime OBJECT ${runtime_src})
add_library(mylib $<TARGET_OBJECTS:runtime>)

This causes the object files from runtime to be used as the sources for mylib (whether it be shared or static.) Since they’re already compiled, they’re just lumped into the library output as-is.

Thanks! That seemed to work for the OBJECT library.

What about the imported targets I created for 3rd party dependencies? Those appear on the linker line too, but they look like MyProj_dep, which obviously isn’t standard.

It seems that if I do that, then interface properties on the object library no longer propagate. Hm. I was able in my case to move those properties up to the parent library. But is there some way to get the best of both worlds?

You should be able to export the OBJECT library. I believe it just turns into an INTERFACE library when installed (unless OBJECTS DESTINATION is given). At least that was the plan when we started making them better CMake citizens.

Cc: @brad.king @robert.maynard

Yes, installing and exporting an OBJECT library without any OBJECTS DESTINATION will turn it into an INTERFACE library. That can be used to propagate usage requirements to the application that your real library has transitively through its use of the object library. This is important when your real library is a static library because it can have link dependencies that come from object files in the object library, and only the object library target has the needed INTERFACE_LINK_LIBRARIES on it.

See also discussion in CMake Issue 15415.

1 Like