[CMake] Transitive linking

Alexander Neundorf a.neundorf-work at gmx.net
Sat Nov 19 03:21:05 EST 2011


On Saturday 19 November 2011, Michael Hertling wrote:
> On 11/18/2011 10:03 PM, James Bigler wrote:
> > 2011/11/18 Alexander Neundorf <a.neundorf-work at gmx.net>
> > 
> >> On Friday 18 November 2011, James Bigler wrote:
> >>> I thought CMake knew how to not drag all the dependent libraries once
> >>> you linked an executable module.
> >>> 
> >>> add_library(A STATIC a.cpp)
> >>> add_library(B SHARED b.cpp)
> >>> target_link_libraries(B A)
> >>> add_library(C SHARED c.cpp)
> >>> target_link_libraries(C B)
> >>> 
> >>> add_executable(run run.cpp)
> >>> target_link_libraries(run C)
> >>> 
> >>> At this point I'm seeing that C links against B and A when I think it
> >>> should only link against B since A shouldn't be needed to link against
> >>> B. In addition when compiling run, it links against B and A.
> >>> 
> >>> /usr/bin/c++   -dynamiclib -Wl,-headerpad_max_install_names   -o
> >> 
> >> libC.dylib
> >> 
> >>> -install_name
> >>> /Users/jbigler/tmp/code/cmake/translinking/build/libC.dylib
> >>> CMakeFiles/C.dir/c.cpp.o libB.dylib libA.a
> >>> /usr/bin/c++    -Wl,-search_paths_first
> >>> -Wl,-headerpad_max_install_names CMakeFiles/run.dir/run.cpp.o  -o run 
> >>> libC.dylib libB.dylib libA.a
> >>> 
> >>> Is this the expected behavior?
> >> 
> >> Yes.
> >> If you want to limit this, use target_link_libraries( C
> >> LINK_INTERFACE_LIBRARIES ... ), with this you can specify the
> >> transitively linked libraries when linking against C.
> >> 
> >> Alex
> > 
> > OK, so propagating the libraries is the default behavior.  I tried to use
> > LINK_INTERFACE_LIBRARIES, but it only seemed to work for static
> > libraries:
> > 
> > add_library(A STATIC a.cpp)
> > add_library(B SHARED b.cpp)
> > target_link_libraries(B A)
> > target_link_libraries(B LINK_INTERFACE_LIBRARIES)
> > add_library(C SHARED c.cpp)
> > target_link_libraries(C B)
> > target_link_libraries(C LINK_INTERFACE_LIBRARIES)
> > 
> > add_executable(run run.cpp)
> > target_link_libraries(run C)
> > 
> > During build:
> > 
> > Build B (this is fine)
> > /usr/bin/c++   -dynamiclib -o libB.dylib CMakeFiles/B.dir/b.cpp.o libA.a
> > Build C (this is fine too, no A in the list)
> > /usr/bin/c++   -dynamiclib -o libC.dylib CMakeFiles/C.dir/c.cpp.o
> > libB.dylib Build run (this is weird, it linked both B and C)
> > /usr/bin/c++    CMakeFiles/run.dir/run.cpp.o  -o run  libC.dylib
> > libB.dylib
> > 
> > Did I specify something wrong or does this property only consider static
> > libraries?
> 
> On *nix, I can't confirm this:
> 
> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
> PROJECT(TRANSLINK CXX)
> SET(CMAKE_VERBOSE_MAKEFILE ON)
> FILE(WRITE ${CMAKE_BINARY_DIR}/a.cxx "void a(){}\n")
> ADD_LIBRARY(A STATIC a.cxx)
> FILE(WRITE ${CMAKE_BINARY_DIR}/b.cxx "void b(){}\n")
> ADD_LIBRARY(B SHARED b.cxx)
> TARGET_LINK_LIBRARIES(B A)
> TARGET_LINK_LIBRARIES(B LINK_INTERFACE_LIBRARIES)
> FILE(WRITE ${CMAKE_BINARY_DIR}/c.cxx "void c(){}\n")
> ADD_LIBRARY(C SHARED c.cxx)
> TARGET_LINK_LIBRARIES(C B)
> TARGET_LINK_LIBRARIES(C LINK_INTERFACE_LIBRARIES)
> FILE(WRITE ${CMAKE_BINARY_DIR}/main.cxx "int main(){}\n")
> ADD_EXECUTABLE(main main.cxx)
> TARGET_LINK_LIBRARIES(main C)
> 
> The main target's link command line reads:
> 
> .../c++ .../main.cxx.o -o main ... libC.so ...  # No libB.so!
> 
> Do you actually get different results with the above-noted project?
> 
> In general, CMake's transitive handling of target dependencies causes
> no harm since no library is loaded unnecessarily, although there may be
> libraries which are specified unnecessarily. E.g., main would be linked
> against libB.so without immediately referring to the latter, i.e. it is
> formally overlinked, but whether libB.so is loaded on behalf of main or
> on behalf of libC.so does not matter, 

It matters a bit.
IIRC this increases startup time and some memory consumption (I don't remember 
the details, and it's not much, but it's not zero), and also adds unnecessary 
dependencies for packagers.

Alex


More information about the CMake mailing list