I have a project where both static and shared libraries are built from the same sources. The static library uses object files built using -fPIC
. For now, I have come to the conclusion this is essentially a flawed approach because of the way OBJECT
libraries in CMake propagate their private dependencies, but I may be wrong. Consider the following CMake project, where libuuid
is some random 3rd-party dependency to illustrate the problem:
find_package(PkgConfig REQUIRED)
pkg_check_modules(UUID REQUIRED uuid IMPORTED_TARGET)
# Object library.
add_library(foo-object OBJECT)
target_sources(foo-object PRIVATE foo.cpp foo.h)
target_link_libraries(foo-object PRIVATE PkgConfig::UUID)
# Shared library built using the object from the object library.
add_library(foo-shared SHARED)
target_link_libraries(foo-shared PUBLIC foo-object)
# Shared library without an intermediate object library.
add_library(bar-shared SHARED)
target_sources(bar-shared PRIVATE foo.cpp foo.h)
target_link_libraries(bar-shared PRIVATE PkgConfig::UUID)
# Two different executables, using either one of the shared libraries defined above.
add_executable(foo-test)
target_link_libraries(foo-test PRIVATE foo-shared)
target_sources(foo-test PRIVATE test.cpp)
add_executable(bar-test)
target_link_libraries(bar-test PRIVATE bar-shared)
target_sources(bar-test PRIVATE test.cpp)
In short; this builds two shared libraries, foo-shared
and bar-shared
, where foo-shared
is built from an OBJECT
library, and bar-shared
is built directly from sources.
When linking the test binaries foo-test
and bar-test
, the link commands look roughly as follows:
/usr/bin/c++ test.cpp.o -o bar-test libbar-shared.so
/usr/bin/c++ test.cpp.o -o foo-test libfoo-shared.so /usr/lib/libuuid.so
So the problem here is that libuuid.so
ends up in the linker command when linking libfoo-shared.so
, even though it is a private dependency of foo-object
. So essentially foo-object
's dependencies are treated in the same way as static library dependencies. This is the dependency graph generated by CMake:
The question now is; are object libraries a fundamentally flawed approach when building static and shared libraries from the same object files because of this issue or am I missing something? Is there another way to prevent building all sources twice when building both a static and shared library from the same objects in CMake?