[英]Using --whole-archive linker option with CMake and libraries with other library dependencies
我有一個項目,它曾經是一組巨大的源文件,所有文件都被編譯然后鏈接為一個可執行文件。 作為使項目更加模塊化的第一步,我將構建分解為幾個更小的塊並使其成為靜態庫。 有一個層次結構,因此Exe1
將鏈接到靜態庫Lib2A
和Lib2B
。 Lib2A
將依賴於靜態Lib3A
、 lib3B
、 lib3C
等。這里的數字顯示了它們在層次結構中的層。
問題是我需要在鏈接時使用--whole-archive
,否則找不到來自底層庫的某些符號。
當我為Exe1
的鏈接添加以下內容時:
target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)
我最終得到了一個實際的鏈接階段命令,例如:
g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a
不可避免地,一些第 3 層靜態庫中的符號會丟失,並且我會出現丟失符號錯誤。
我預計因為Lib2A
將Lib3*
庫作為依賴項,所以它們也將在鏈接器命令的--whole-archive
部分“內部”,但它們會出現在外部。
我嘗試了許多不同的組合(例如將--whole-archive
東西放在較低層),但還沒有遇到使用 CMake 的方法。 我究竟做錯了什么?
謝謝
對於 3.12 和更新版本的 CMake,我會使用對象庫。
我為早於該版本的版本找到的解決方法是創建一個中間靜態庫,該庫使用一些屬性魔法將所有鏈接依賴項放在 --whole-archive 部分中。 對我來說,頂級靜態庫被稱為“源”。 它本身實際上不包含任何內容,但對一堆其他靜態庫具有鏈接依賴關系。 我創建了“源組合”,如下所示:
add_library(source-combined STATIC "")
set_target_properties(source-combined PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(source-combined PUBLIC
-Wl,--whole-archive
$<TARGET_PROPERTY:source,INTERFACE_LINK_LIBRARIES>
-Wl,--no-whole-archive
)
現在,當我通過鏈接這個源組合庫來創建可執行文件或共享庫時,我得到了 --whole-archive 和 --no-whole-archive 作為整個靜態庫集的書擋,這些靜態庫是鏈接依賴項'資源'。 偶然發現這種技術需要很長時間,所以我正在分享它。
以下對我有用。 考慮兩個庫:
我們想要 my_clib 的整個存檔,以及指向它的 my_platform 鏈接。
add_library(my_platform INTERFACE) # this could also be a regular library
add_library(my_clib STATIC)
target_sources(my_clib
PRIVATE
gcc_newlib_nano.c
gcc_newlib_nano_cpp.cc
)
# Link my_clib and any other libs
target_link_libraries(my_platform
INTERFACE
my_clib
)
# Ensure the whole archive is linked
target_link_options(my_platform
INTERFACE
-Wl,--whole-archive ${CMAKE_CURRENT_BINARY_DIR}/libmy_clib.a -Wl,--no-whole-archive
)
作為上述答案的替代方案,我需要快速而骯臟地查看添加整個存檔目標標志(或將代碼庫轉換為對象庫......)的努力是否是正確的解決方案。 通過遵循默認鏈接命令的CMake 源代碼,我將項目的命令修改為:
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--start-group -Wl,--whole-archive <LINK_LIBRARIES> -Wl,--no-whole-archive -Wl,--end-group")
它奏效了! 雖然不是最好的解決方案,但它至少會很快得到一些結果。
如果您需要使用鏈接器選項--whole-archive
,那么您肯定應該使用對象庫:
# Lib2A/CMakeLists.txt
add_library(Lib2A OBJECT ${Lib2A_SRC})
# Lib2B/CMakeLists.txt
add_library(Lib2B OBJECT ${Lib2B_SRC})
它是可移植的,不需要使用鏈接器選項--whole-archive
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.