[CMake] Link order and interface multiplicity

Patrick Boettcher patrick.boettcher at posteo.de
Tue May 16 04:39:42 EDT 2017


Hi,

On Mon, 15 May 2017 12:30:10 +0000
Etan Kissling <kissling at oberon.ch> wrote:
> I have a project with a layer consisting of interface libraries:
> 	add_library(I INTERFACE)
> 
> These interface libraries are then implemented several times, to fit
> the different environments of applications: add_library(IA STATIC ...)
> 	target_link_libraries(IA PUBLIC I)
> 
> 	add_library(IB STATIC ...)
> 	target_link_libraries(IB PUBLIC I)
> 
> There are also application independent libraries, that make use of
> the interface libraries. add_library(Foo STATIC ...)
> 	target_link_libraries(Foo PUBLIC I)
> 
> 	add_library(Bar STATIC ...)
> 	target_link_libraries(Bar PUBLIC I)
> 
> And finally, the application defines which implementation of the
> interface library layer is being used. 
>
>	add_executable(ExeA ...)
> 	target_link_libraries(ExeA Foo Bar IA)
> 
> 	add_executable(ExeB ...)
> 	target_link_libraries(ExeB Foo Bar IB)
> 
> 
> Luckily, this is okay, as long as IA is listed after Foo and Bar in
> the synthesized link command.
> 
> However, certain implementations of I make use of the application
> independent libraries again. On these environments, the link command
> line becomes something like this: 
>
> IA Foo Bar
> 
> While it should be
>
> Foo Bar IA Foo Bar
> 
> This make sense, because there is no explicit dependency being
> described that Foo / Bar depend on IA while compiling ExeA. In the
> simple case, we just get lucky, because it happens to be the default
> that link command line has the same order as in the
> target_link_libraries call.

I wouldn't try my luck if I were you. Always be explicit, especially
with dependencies, otherwise, at some point in time, cmake won't get it
right when generating the order of link.

What you could try is "forward" declaring a
platform/app-dependent dependencies with interface libraries:

In CMakeLists.txt

  add_library(top-level-I INTERFACE)
  target_link_libraries(top-level-I INTERFACE app-dependent-I) 
    # here we forward declare app-dependent-I

  add_subdirectory(app) # app-dependent

  add_executable(test2 test2.cpp)
  target_link_libraries(test2 top-level-I) # will link with IA and IB

In app/CMakeLists.txt

  add_library(app-dependent-I INTERFACE)
  target_link_libraries(app-dependent-I INTERFACE IA IB)
    # here we "implement" 

  add_library(IA ...)
  add_library(IB ...)

app-dependent-I is a forward declared libraries - cmake will evaluate
this at generation-time. This will get you the dependencies right.

I hope I correctly understood your question.

--
Patrick.


More information about the CMake mailing list