CMake: how create a single shared library from all static libraries of subprojects?

后端 未结 5 589
南旧
南旧 2020-11-30 19:36

I have the following layout:

top_project
    + subproject1
    + subproject2

Each of subproject1 and subproject2

5条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-30 19:48

    My solution is simply to add /WHOLEARCHIVE, -all_load, or --whole-archive to the linker flags, so that when your main library is linked, all of the sub libraries are included, including all their symbols (the default behaviour is to only include symbols of the sub libraries that are used by the main library. For example:

    Source Files

    $ echo "void Func1() { }" > source1.cpp
    $ echo "void Func2() { }" > source2.cpp
    $ echo "void Func3() { }" > source3.cpp
    $ echo "void Func4() { }" > source4.cpp
    

    Naive CMakeLists.txt

    cmake_minimum_required(VERSION 3.7)
    
    # The 'sub' libraries, e.g. from an `add_subdirectory()` call.
    add_library(sublib_a STATIC source1.cpp source2.cpp)
    add_library(sublib_b STATIC source3.cpp source4.cpp)
    
    # The main library that contains all of the sub libraries.
    add_library(mainlib SHARED)
    
    target_link_libraries(mainlib sublib_a sublib_b)
    

    Running it (on OSX):

    $ make VERBOSE=1
    ...
    [100%] Linking CXX shared library libmainlib.dylib
    /usr/local/Cellar/cmake/3.7.1/bin/cmake -E cmake_link_script CMakeFiles/mainlib.dir/link.txt --verbose=1
    /Library/Developer/CommandLineTools/usr/bin/c++   -dynamiclib -Wl,-headerpad_max_install_names  -o libmainlib.dylib -install_name @rpath/libmainlib.dylib  libsublib_a.a libsublib_b.a 
    [100%] Built target mainlib
    
    $ nm libmainlib.dylib | grep Func
    $
    

    Correct CMakeLists.txt

    Append this:

    # By default, symbols provided by the sublibs that are not used by mainlib (which is all of them in this case)
    # are not used. This changes that.
    if (WIN32)
        set_target_properties(mainlib PROPERTIES
            LINK_FLAGS "/WHOLEARCHIVE"
        )
    elseif (APPLE)
        set_target_properties(mainlib PROPERTIES
            LINK_FLAGS "-Wl,-all_load"
        )
    else ()
        set_target_properties(mainlib PROPERTIES
            LINK_FLAGS "-Wl,--whole-archive"
        )
    endif ()
    

    Running it (note the extra -all_load):

    $ make VERBOSE=1
    [100%] Linking CXX shared library libmainlib.dylib
    /usr/local/Cellar/cmake/3.7.1/bin/cmake -E cmake_link_script CMakeFiles/mainlib.dir/link.txt --verbose=1
    /Library/Developer/CommandLineTools/usr/bin/c++   -dynamiclib -Wl,-headerpad_max_install_names -Wl,-all_load -o libmainlib.dylib -install_name @rpath/libmainlib.dylib  libsublib_a.a libsublib_b.a 
    [100%] Built target mainlib
    
    $ nm libmainlib.dylib | grep Func
    0000000000001da0 T __Z5Func1v
    0000000000001db0 T __Z5Func2v
    0000000000001dc0 T __Z5Func3v
    0000000000001dd0 T __Z5Func4v
    

    Note that I've only actually tested -all_load so far, and /WHOLEARCHIVE is an MSVC 2015 option.

提交回复
热议问题