If I specify a dependency chain of OBJECT
libraries in CMake, only the target_link_libraries
dependencies of the very last one is used in the target executable.
Minimal Example:
main
depends on objB
, which depends on objA
.
Both objA
and objB
are OBJECT
libraries in CMake.
I would expect main
to link with both object files. It doesn't.
cmake_minimum_required(VERSION 3.13)
project(transitive-object-library-link-issue VERSION 1.0.0 LANGUAGES C)
add_library(objA OBJECT a.c)
add_library(objB OBJECT b.c)
target_link_libraries(objB PUBLIC objA)
# Should link with 'a.o', since 'objA' is "linked" by 'objB'
add_executable(main main.c)
target_link_libraries(main objB)
Note: A working set of files are available at https://github.com/scraimer/cmake-transitive-object-library-link-issue
If I change objA
to a non-OBJECT
library, the problem is eliminated by getting rid of the chain of OBJECT
library dependencies. In other words, change the line
add_library(objA OBJECT a.c)
To be:
add_library(objA a.c)
So it's something specific to OBJECT
libraries. How should I be specifying the dependencies to make main
link with objA
? (Without having to specify objA
in every executable target that uses objB
)
target_link_libraries is probably the most useful and confusing command in CMake. It takes a target ( another ) and adds a dependency if a target is given. If no target of that name ( one ) exists, then it adds a link to a library called one on your path (hence the name of the command).
To add a library in CMake, use the add_library() command and specify which source files should make up the library. Rather than placing all of the source files in one directory, we can organize our project with one or more subdirectories. In this case, we will create a subdirectory specifically for our library.
There is negligible performance penalty for having two separate target_link_libraries calls.
Object library targets are not real libraries, they are simply a collection of objects, but they are not really linked together until they are used to build a real target like an executable or shared/static library. Citing the linked documentation:
add_library(<name> OBJECT <src>...)
Creates an Object Library. An object library compiles source files but does not archive or link their object files into a library.
In despite of that, you can apply a target_link_library()
command to an object library, but only to specify dependencies of their sources on other libraries. The linked documentation explains your problem:
The object library’s usage requirements are propagated transitively [...], but its object files are not.
Object Libraries may “link” to other object libraries to get usage requirements, but since they do not have a link step nothing is done with their object files.
So, the transitive propagation affects only to compile definitions and dependencies of other real libraries, not the objects themselves.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With