[cmake-developers] Object library linking (and a bit about INTERFACE_SOURCES)
Stephen Kelly
steveire at gmail.com
Wed Feb 25 17:43:18 EST 2015
Ben Boeckel wrote:
>> It is just as easy to get into this situation when linking static
>> libraries, right? Object libraries are not part of the problem, right? Or
>> could you post a sscce?
>
> It is, so maybe it's less of an issue. I just think it is much easier to
> stumble upon it when you start throwing objects directly into link lines
> implicitly rather than with a staticWithGlobalStatic -> {sharedA,
> sharedB} -> exeUsingAandB setup.
Right. Consider
add_library(upstream ...)
add_library(middle ...)
target_link_libraries(middle ${SCOPE} upstream}
add_executable(consumer1)
target_link_libraries(consumer1 middle)
add_library(consumer2 SHARED)
target_link_libraries(consumer2 middle)
We have these possible scenarios (omitting INTERFACE scope, and omitting
middle=OBJECT because I think it doesn't change anything):
upstream SCOPE middle
---------- --------- --------
STATIC PRIVATE STATIC
OBJECT PRIVATE STATIC
STATIC PUBLIC STATIC
OBJECT PUBLIC STATIC
STATIC PRIVATE SHARED
SHARED PRIVATE SHARED
OBJECT PRIVATE SHARED
STATIC PUBLIC SHARED
SHARED PUBLIC SHARED
OBJECT PUBLIC SHARED
Omitting the upstream = SHARED or STATIC cases too, because I think they're
not relevant to this discussion.
upstream SCOPE middle
---------- --------- --------
OBJECT PRIVATE STATIC
OBJECT PUBLIC STATIC
OBJECT PRIVATE SHARED
OBJECT PUBLIC SHARED
If middle is STATIC, and SCOPE is PRIVATE, then the upstream objects are
archived together with the rest of middle. Consumers use middle as if the
upstream objects were not declared separately.
If SCOPE is PUBLIC, perhaps it should be treated as PRIVATE or INTERFACE?
That is, either not archive the upstream objects with middle (letting
downstreams link the objects directly instead), or not link them in with
downstreams (which will get them anyway through linking with middle).
If middle is SHARED and scope is PRIVATE, then there is no problem (Except
perhaps the global object issue, but that is present also if upstream is
STATIC and it can be argued that no library should legitimately do that
anyway).
If middle is SHARED and scope is PUBLIC, then the situation is very similar
to upstream=STATIC, in that the objects get compiled into middle and into
each of the consumers. Is this an undesired effect?
Let's imagine upstream is statically compiled zlib and middle is the
FooCompress library which uses zlib in its implementation and uses zlib
headers in FooCompress.h, but doesn't dllexport the zlib symbols (Is that a
realistic scenario?), and expects consumers to also link the zlib.a instead.
I have trouble imagining any other reason a SHARED library would PUBLIC link
a STATIC or OBJECT library otherwise. But in the scenario I described,
consumers must link the zlib.a (or .o), right?
Or should it be prohibited to put OBJECT libraries in the INTERFACE of
SHARED libraries?
Again, even if the upstream is STATIC, this is a problem only in the
presence of global objects provided by upstream.
>> > For the diamond-usage problem, is there some way of utilizing the
>> > COMPATIBLE_INTERFACES to deny the mixing of two libraries where each
>> > built with an object libraries' objects? Having a property to trigger
>> > that would be nice...
>>
>> Yes, that's possible by adding an ExclusiveList compatible type and
>> populating an appropriate property when linking to OBJECT libraries. I've
>> written a prototype and can clean it up and post it if that's part of the
>> solution.
>
> As long as it is opt-in, I'm fine with this (it only really makes sense
> in the presence of global statics with dtors).
That appears to be the only problem being discussed here. I'm sure
ExclusiveList could help, but in the case you describe, CMake wouldn't
populate anything automatically (thereby making it opt-in).
>> > Until that problem is solved we cannot make object libraries
>> > implicitly offer their objects just through tll().
>>
>> Honestly, the problem is still not clear to me. Is it something you would
>> want to write and expect to be correct, but which would actually be
>> incorrect? Is the static global object instance a necessary part of the
>> problem-scenario?
>
> So this problem came up in a project where the current code uses LIBADD
> in autotools. These added libraries are conditionally built and have
> varying usage requirements (headers, linking, defines, etc.). Oh, they
> also have symbols which need exporting.
What is the type of these libraries? I'm guessing SHARED as you talk about
exporting.
> Yes, I already tried using static libraries (I think $<LINK_ONLY> made
> the duplicate symbols occur in dependent projects which use shared libs
> through the transitive linking which then all went into an executable);
> that's how I ended up trying object libraries.
Maybe something I wrote above is fuel for thought here?
Thanks,
Steve.
More information about the cmake-developers
mailing list