cmake:target_link_libraries使用不共享的静态库

时间:2016-04-20 20:09:00

标签: c++ linux cmake

是否可以告诉cmake链接静态库而不是共享

CMakeLists.txt的顶部,我配置了以下内容:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})

稍后,我添加了一个二进制文件,并告诉它在发布模式下链接tcmalloc

target_link_libraries(${BIN_NAME} optimized tcmalloc_minimal)

生成的makefile链接共享版本tcmalloc

$ make VERBOSE=1 | grep tcmalloc
/usr/bin/c++ ... -Wl,-Bdynamic ltcmalloc_minimal 

进一步证明:

$ ldd app 
    ...
    libtcmalloc_minimal.so.4 => /usr/local/lib/libtcmalloc_minimal.so.4 (0x00007eff89733000)
    ...

存在tcmalloc的静态和共享版本:

$ ls -1 /usr/local/lib/libtcmalloc_minimal*
/usr/local/lib/libtcmalloc_minimal.a
/usr/local/lib/libtcmalloc_minimal_debug.a
/usr/local/lib/libtcmalloc_minimal_debug.la
/usr/local/lib/libtcmalloc_minimal_debug.so
/usr/local/lib/libtcmalloc_minimal_debug.so.4
/usr/local/lib/libtcmalloc_minimal_debug.so.4.2.6
/usr/local/lib/libtcmalloc_minimal.la
/usr/local/lib/libtcmalloc_minimal.so
/usr/local/lib/libtcmalloc_minimal.so.4
/usr/local/lib/libtcmalloc_minimal.so.4.2.6

问题:

如何配置cmake以链接静态版tcmalloc

3 个答案:

答案 0 :(得分:1)

您可以创建一个帮助函数,在函数范围(so therefore doesn't affect the parent scope)设置CMAKE_FIND_LIBRARY_SUFFIXES,该函数搜索相关库并使用结果设置输出变量

function(find_static_library LIB_NAME OUT)

    if (WIN32 OR MSVC)
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
    elseif (UNIX)
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
    endif()      

    find_library(
        FOUND_${LIB_NAME}_STATIC
        ${LIB_NAME}
        )

    if (FOUND_${LIB_NAME}_STATIC)
        get_filename_component(ABS_FILE ${FOUND_${LIB_NAME}_STATIC} ABSOLUTE)
    else()
        message(SEND_ERROR "Unable to find library ${LIB_NAME}")
    endif()

    set(${OUT} ${ABS_FILE} PARENT_SCOPE)

endfunction()

然后,您可以从CMakeLists.txt中的某个位置调用此函数,以使用库的位置填充变量。

未能找到它会导致硬故障

find_static_library(tcmalloc_minimal TCMALLOC)

然后,您可以在调用target_link_libraries时使用此变量,并确保链接到静态版本

target_link_libraries(${BIN_NAME} optimized ${TCMALLOC})

在这里你可以看到结果:

$ make VERBOSE=1 | grep tcmalloc
/usr/bin/c++ ... /usr/local/lib/libtcmalloc_minimal.a ...

答案 1 :(得分:1)

如果您只需要支持非Windows平台,那么来自其中一个Kitware开发人员的CMake邮件列表中的this old email提供了最简单的方法。本质上,使用find_library()来查找实际库的位置,通过首先在要查找的名称中列出静态库来支持静态库。即。

find_library(TCMALLOC_LIB NAMES libtcmalloc_minimal.a tcmalloc_minimal)

然后,您将链接到以常规方式找到的库:

target_link_libraries(${BIN_NAME} ${TCMALLOC_LIB})

如果您需要支持静态库的名称不是lib???.a的平台,那么您可以更明智地定义静态库名称的定义方式。您可以使用CMAKE_STATIC_LIBRARY_PREFIX和CMAKE_STATIC_LIBRARY_SUFFIX变量。

在Windows上,问题在于您无法区分静态库和DLL的导入库,如Kitware错误跟踪器中this old issue中所述。它们都具有文件扩展名.lib,因此如果特定文件是静态库,则无法使用该扩展来计算,与基于Unix的平台不同。

答案 2 :(得分:-1)

您必须以这种方式设置CMAKE_FIND_LIBRARY_SUFFIXES变量:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a)

因为默认情况下CMAKE_FIND_LIBRARY_SUFFIXES也有.so后缀(似乎没有按插入顺序搜索)。为了允许可移植性,应添加其他后缀(有关不同平台上CMAKE_FIND_LIBRARY_SUFFIXES的默认值,请参阅here)。