[CMake] Link order and interface multiplicity

Etan Kissling kissling at oberon.ch
Wed May 17 08:28:33 EDT 2017


Hi, and thanks for the quick reaction :-)

The approach with forward declaration looks interesting. However, I don't think that it will resolve all the problems.

One issue is that there are multiple apps, each using separate implementations.
• ExeA uses the generic libraries Foo and Bar, as well as the **IA** implementation of interface library I.
• ExeB uses the generic libraries Foo and Bar, as well as the **IB** implementation of interface library I.

On top of that, I'd like to be able to build Foo and Bar independently as static libraries, without IA or IB being present.

Is it possible to replace references to interface library I with implementation IA, but only while ExeA is being compiled, and vice versa for ExeB? 
There are only static libraries involved, so the compilation of Foo / Bar should be the same in both cases.

Thanks

Etan



> On 16 May 2017, at 10:39, Patrick Boettcher <patrick.boettcher at posteo.de> wrote:
> 
> 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