Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make `target_link_libraries` dependencies transitive from OBJECT libraries in cmake?

Tags:

cmake

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)

like image 785
Shalom Craimer Avatar asked Dec 05 '19 10:12

Shalom Craimer


People also ask

How does CMake target_link_libraries work?

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).

How do I link a .LIB file to CMake?

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.

Can target_link_libraries be called multiple times?

There is negligible performance penalty for having two separate target_link_libraries calls.


1 Answers

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.

like image 155
Former contributor Avatar answered Oct 05 '22 18:10

Former contributor