cmake - visual - vs2017 version




CMake:如何從子項目的所有靜態庫創建單個共享庫? (3)

另一種方式。

這種方式似乎更簡單,但我不確定它是多麼完美:

https://stackoverflow.com/a/14347487/602340

我有以下佈局:

top_project
    + subproject1
    + subproject2

subproject1subproject2每一個都創建一個靜態庫。 我想在top_project級別的單個共享庫中鏈接這些靜態庫。

我到目前為止收集的信息是:

  • 使用-fPic編譯(除了Windows之外的所有內容都需要)以創建與位置無關的代碼,這將允許將靜態庫鏈接到單個共享庫或解壓縮所有靜態庫(例如使用ar )並將它們重新鏈接到共享庫(我認為這是一個不雅和不便攜的解決方案)
  • 必須將所有源文件顯式地提供給add_library命令:由於某些我無法理解的原因,只需編寫add_library(${PROJECT_NAME} SHARED subproject1 subproject2)就無法正常工作(它實際上創建了一個空庫並且沒有註冊依賴項正確)
  • 在CMake中有一個OBJECT庫功能,但我不認為它的目的是真正做我想要的。

有什麼想法嗎?


另一種方法是提供源文件的路徑和所有項目的頭文件,並將它們組合在一起以生成.so。 這通常是推薦的方法,而不是創建靜態庫,然後創建一個共享庫。

基本上你應該做以下事情:

FILE(GLOB subproject1_sources
  <sub_project1_lib_sources_dir>/file1.c
  <sub_project1_lib_sources_dir>/file2.c //... etc
)

FILE(GLOB subproject2_sources
  <sub_project2_lib_sources_dir>/file1.c
  <sub_project2_lib_sources_dir>/file2.c //... etc
)

FILE(GLOB topProject_sources
  <top_project_lib_sources_dir>/file1.c
  <top_project_lib_sources_dir>/file2.c //... etc
)

include_directories("<sub_project1_lib_sources_dir>")
include_directories("<sub_project2_lib_sources_dir>")
include_directories("<top_project_lib_sources_dir>") //should be "." if you're building from here

add_library(topProject SHARED ${topProject_sources} ${subproject1_sources} ${subproject2_sources})

我的解決方案只是將/WHOLEARCHIVE-all_load-all_load --whole-archive到鏈接器標誌,這樣當鏈接主庫時,包括所有子庫,包括它們的所有符號(默認行為是僅包含主庫使用的子庫的符號。例如:

源文件

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

天真的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)

運行它(在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
$

糾正CMakeLists.txt

附加:

# 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 ()

運行它(注意額外的-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

請注意,到目前為止,我實際上只測試了-all_load ,而/WHOLEARCHIVE是一個MSVC 2015選項。







shared-libraries