goneskiing
goneskiing

Reputation: 1819

Transitive dependencies and OBJECT libraries

A somewhat similar question was asked here, Transitive target_include_directories on OBJECT libraries, but there was no real solution.

If I have a project b that depends on a project a I can build them as follows

add_library(a OBJECT ${a_srcs})
add_library(b OBJECT ${b_srcs})

When I want to build an excutable using I them I can write

add_executable(p ${p_srcs} $<TARGET_OBJECTS:b> $<TARGET_OBJECTS:a>)

Is there any way to not have to specify $<TARGET_OBJECTS:a>? I assume this means telling CMake in some way that there is a dependency. If I was building SHARED libraries rather than OBJECT ones the b project would contain

target_link_libraries(b a)

which creates this dependency, but I can't find some equivalent way for OBJECT libraries.

Upvotes: 2

Views: 920

Answers (2)

TallChuck
TallChuck

Reputation: 1972

The best way I have found to do this is to wrap the OBJECT library in an INTERFACE library.

add_library(a-objects OBJECT ${a_srcs})
add_library(b-objects OBJECT ${b_srcs})

add_library(a INTERFACE)
add_library(b INTERFACE)

target_link_libraries(a INTERFACE a-objects)
target_link_libraries(b INTERFACE b-objects)

target_sources(a INTERFACE $<TARGET_OBJECTS:a-objects>)
target_sources(b INTERFACE $<TARGET_OBJECTS:b-objects>)

My rule is to use the OBJECT library to set requirements, but only ever link against the INTERFACE library.

target_link_libraries(b-objects INTERFACE a)

Setting it up this way should allow you to link against both libraries like this:

add_executable(p ${p_srcs})
target_link_libraries(p PRIVATE b)

Upvotes: 0

svenevs
svenevs

Reputation: 863

Insofar as I understand it, in the current setup, no. The add_executable for target p can either

  1. Link against some library (shared or static), or
  2. Merge object sources into itself.

You have chosen (2). The only other option I see here is create a third library c that merges in a and b into a full-blown library (see Usage section at the bottom, which is likely where you were already looking).

When you do that, you could then target_link_libraries(c). The compiled OBJECTs cannot be linked against on their own. You have to merge the sources into either an executable or a library for them to be used.

Your add_executable call could be thought of basically doing add_executable(p ${p_srcs} ${a_srcs} ${b_srcs}), only instead of compiling a_srcs and b_srcs (which has been done previously), just copy in the compiled objects instead of redoing the work. That's a really simple / bad explanation, but that's the general idea.

Upvotes: 1

Related Questions