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
原文地址:https://www.cnblogs.com/coding-my-life/p/14018972.html