CMake優先鏈接靜態庫


當使用CMake來生成編譯腳本時,如果需要鏈接其他庫文件,一般使用target_link_libraries,如:

target_link_libraries(master
    flatbuffers
    mariadbclient
    ssl
    crypto
    dl
    rt
    pthread
    resolv
    z
)

默認情況下,這個是鏈接動態庫的。不過很多時候為了方便部署,需要靜態鏈接部分靜態鏈庫,有幾種方式可以試下:

  • 直接寫死靜態庫的完整路徑
target_link_libraries(master
    /usr/local/lib/libflatbuffers.a
)
  • 自動查找靜態庫

上面直接寫死庫文件的完整路徑,可移植性大打折扣。CMake的好處本身就是跨平台的,各個平台的庫文件路徑不一樣,可以使用find_library來獲取完整路徑。不過find_library默認情況下是優先查找動態庫的,需要改一下

if (WIN32 OR MSVC)
    set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
elseif (UNIX)
    # 僅查找靜態庫,強制后綴為 .a
    set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")

    # 如果只是優先查找靜態庫,保證 .a 后綴在前面即可,把默認的后綴加上
    # set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()

find_library(FLATBUFFERS_LIB flatbuffers)
target_link_libraries(master
    ${FLATBUFFERS_LIB}
)

# 當然,這個可能更簡單,只是也不跨平台罷了
find_library(FLATBUFFERS_LIB libflatbuffers.a)
  • 直接指定庫文件后綴或者名字
target_link_libraries(master
    libflatbuffers.a
)

# 或者
target_link_libraries(master
    flatbuffers.a
)

上面的寫法都會查找靜態庫,只不過不跨平台(win下后綴是.lib)。

  • 使用編譯參數
target_link_libraries(master
    -Wl,-Bstatic
    flatbuffers
    -Wl,-Bdynamic
)

target_link_libraries里是可以加編譯參數的。在庫名字的前后,可以直接指定編譯參數強制使用靜態庫,只不過同樣不跨平台,畢竟GCC和MSBuild的參數可差遠了。

總而言之,目前官方是沒有直接提供一個優先鏈接靜態庫的選項,比較推薦的是修改find_library優先級的方式,畢竟還有if else控制一下,可以處理跨平台的情況。但很多情況下跨平台也不一定是跨編譯器,比如我一般寫的Linux下的程序,到win下是用mingw編譯器,所以全部都用.a后綴是沒有問題的。

target_link_libraries有提到

Library dependencies are transitive by default with this signature. When this target is linked into another target then the libraries linked to this target will appear on the link line for the other target too.

add_library(lua_flatbuffers STATIC ${SRC_LIST})
target_link_libraries(lua_flatbuffers flatbuffers)

target_link_libraries(master
    lua_flatbuffers
    flatbuffers.a
    ssl
)

上面這個例子,編譯lua_flatbuffers這個靜態庫的時候,依賴flatbuffers。而master依賴lua_flatbuffers,此時CMake會自動把lua_flatbuffers的依賴flatbuffers自動加到master去。即原本master的參數為-Wl,-Bstatic lua_flatbuffers -lflatbuffers -Bdynamic -lssl ,現在卻變成了-Wl,-Bstatic lua_flatbuffers -lflatbuffers -Bdynamic -lssl -lflatbuffers,后面多了一個-lflatbuffers。即使master的庫里強制指定靜態庫,但由於lua_flatbuffers使用的是動態庫,所以最終master使用的也是動態庫。

這個問題讓我查了很久,可以強制清空lua_flatbuffersINTERFACE_LINK_LIBRARIES來解決

set_target_properties(lua_flatbuffers PROPERTIES INTERFACE_LINK_LIBRARIES "")

如果編譯出現問題,cmake之后可以用make VERBOSE=1來編譯程序,各種參數一清二楚,方便查找問題

-o /home/test/code/MServer/server/bin/master -Wl,-Bstatic -llua -luuid -lflatbuffers -lmariadbclient -lmongoc-static-1.0 -lbson-static-1.0 -lsasl2 -Wl,-Bdynamic -Wl,-Bstatic -lz -Wl,-Bdynamic -lssl -lcrypto -ldl -lrt -lpthread -lresolv


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM