MantisBT - CMake
View Issue Details
0013866CMakeCMakepublic2013-01-22 02:112013-06-03 09:05
Alexey Pelykh 
 
normalmajoralways
closedno change required 
x64Ubuntu12.04
CMake 2.8.9 
 
0013866: target_link_libraries does threats '-Wl,--whole-library -lmy_lib -Wl,--no-whole-library' entirely as linker flags
According to documentation:
If a library name matches that of another target in the project a dependency will automatically be added in the build system to make sure the library being linked is up-to-date before the target links. Item names starting with '-', but not '-l' or '-framework', are treated as linker flags.

-lmy_lib must be understood by CMake as library reference, but it does not, since my_lib dependencies (LINK_PUBLIC"ed in my_lib project) does not appear in linking phase of host project
No tags attached.
Issue History
2013-01-22 02:11Alexey PelykhNew Issue
2013-01-23 11:28Brad KingNote Added: 0032130
2013-01-23 11:45Alexey PelykhNote Added: 0032132
2013-01-23 11:51Brad KingNote Added: 0032133
2013-01-23 11:53Alexey PelykhNote Added: 0032134
2013-01-23 11:53Alexey PelykhNote Edited: 0032134bug_revision_view_page.php?bugnote_id=32134#r1008
2013-01-23 13:10Brad KingNote Added: 0032135
2013-01-23 13:24Alexey PelykhNote Added: 0032136
2013-01-23 13:40Brad KingNote Added: 0032137
2013-01-23 13:47Alexey PelykhNote Added: 0032138
2013-01-23 13:54Brad KingNote Added: 0032140
2013-01-23 13:54Brad KingStatusnew => resolved
2013-01-23 13:54Brad KingResolutionopen => no change required
2013-06-03 09:05Robert MaynardNote Added: 0033190
2013-06-03 09:05Robert MaynardStatusresolved => closed

Notes
(0032130)
Brad King   
2013-01-23 11:28   
If you're writing

 target_link_libraries(foo "-Wl,--whole-library -lmy_lib -Wl,--no-whole-library")

then that entire string is considered one flag.

If you're trying to simulate convenience libraries then look at the OBJECT library feature instead. See the OBJECT mode of add_library:

 http://www.cmake.org/cmake/help/v2.8.9/cmake.html#command:add_library [^]
(0032132)
Alexey Pelykh   
2013-01-23 11:45   
if(CMAKE_COMPILER_FAMILY STREQUAL "gcc")
        set(USE_WHOLE_LIBRARY_ "-Wl,--whole-archive -L${CMAKE_LIBRARY_OUTPUT_DIRECTORY} -l")
        set(_USE_WHOLE_LIBRARY " -Wl,--no-whole-archive")
else()
        set(USE_WHOLE_LIBRARY_ "")
        set(_USE_WHOLE_LIBRARY "")
endif()

static_library:
target_link_libraries(static_library LINK_PUBLIC
        dep1
        dep2
)

shared_library:
target_link_libraries(shared_library LINK_PUBLIC
        "${USE_WHOLE_LIBRARY_}static_library${_USE_WHOLE_LIBRARY}"
        dep3
)

As far as I've understood, shared_library should be linked to static_library and dep1, dep2, dep3. But it does not link to dep1 dep2.
Sorry if I miss something.
(0032133)
Brad King   
2013-01-23 11:51   
The use of quotes in the line

 "${USE_WHOLE_LIBRARY_}static_library${_USE_WHOLE_LIBRARY}"

tells CMake that the entire string is a single item. The item starts in "-W" so it is treated as a flag and not a library. Therefore no transitive dependencies can be looked up.
(0032134)
Alexey Pelykh   
2013-01-23 11:53   
Ok, got it. Any legal/proper way to explain to cmake what I want exactly? Or what I'm trying to achieve is improper solution in cmake? Removing quotes is not correct direction, as far as I can see

(0032135)
Brad King   
2013-01-23 13:10   
Link interfaces (LINK_PUBLIC) are dependency lists rather than link lines so putting order-dependent flags in them will not work cleanly. The only order preservation guarantee that target_link_libraries makes is that when linking the target itself the link line will start with what tll specified. Order for transitive parts is not guaranteed. Therefore doing it without quotes won't work as you correctly claim.

It looks like you're trying to inject object files into downstream targets and provide their link-time dependencies. Currently there is no way to do this in CMake through link rules. The OBJECT library feature can inject object files into other targets but it can't do so through link interfaces or provide the link dependencies.

Can you be more specific about the problem you're trying to solve?
(0032136)
Alexey Pelykh   
2013-01-23 13:24   
For reference:
https://github.com/osmandapp/OsmAnd-core/tree/master/targets/.cmake [^]

Generally, we have
libpng, depends on libz
libjpeg
libgif
[several more]
libskia, depends on libpng, libjpeg, libgif, [several more]
libosmand, depends on libskia, libprotobuf

libskia must be included as whole library since inside it uses some "register at runtime" parts, that are thrown away during linking because not referenced directly from libosmand sources. Basically now you should get overall idea of what I'm trying to do. As fallback option, I also can reference these parts from libosmand code to force linker to include them. Maybe this is even better solution.
(0032137)
Brad King   
2013-01-23 13:40   
Re 0013866:0032136: Ahh, resource initialization :)

One problem with your approach is that if libosmand gets linked into multiple shared libraries then you will get problems when both libraries get loaded into a single process. This is generally why object files don't belong in a link interface.

IMO explicit references are the way to go. This is how Qt does it, for example.

I've also designed used some tricks that involve injecting symbol references into application translation units using preprocessor conditions in your header files.
(0032138)
Alexey Pelykh   
2013-01-23 13:47   
Probably I'll do explicit references, since it's most robust and light-weight way. Thanks for details about quotes, it explains much "issues" I've seen while playing with -Wl.
(0032140)
Brad King   
2013-01-23 13:54   
Okay. Resolving as "no change required" because the originally reported issue is expected behavior.
(0033190)
Robert Maynard   
2013-06-03 09:05   
Closing resolved issues that have not been updated in more than 4 months.