简体   繁体   English

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

[英]cmake: target_link_libraries use static library not shared

Is it possible to tell cmake to link against a static library instead of shared ? 是否有可能告诉cmake链接静态库而不是共享

At the top of my CMakeLists.txt I have the following configured: 在我的CMakeLists.txt的顶部,我有以下配置:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})

Later, I add a binary, and tell it to link against tcmalloc in release mode: 后来,我添加了一个二进制文件,并告诉它在发布模式下链接tcmalloc

target_link_libraries(${BIN_NAME} optimized tcmalloc_minimal)

The resulting makefile links aginst the shared version of tcmalloc : 生成的makefile链接共享版本的tcmalloc

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

Further proof: 进一步证明:

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

Both static and shared versions of tcmalloc exist: 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

Question: 题:

How can I configure cmake to link against the static version of tcmalloc ? 如何配置cmake链接到静态版本的tcmalloc

You can create a helper function which sets CMAKE_FIND_LIBRARY_SUFFIXES at function scope ( so therefore doesn't affect the parent scope ) which searches for the library in question and sets an output variable with the result 您可以创建一个辅助函数,在函数作用域中设置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()

You can then call this function from somewhere in your CMakeLists.txt to populate a variable with the location of the library. 然后,您可以从CMakeLists.txt中的某个位置调用此函数,以使用库的位置填充变量。

Failure to find it results in a hard failure 未能找到它会导致硬故障

find_static_library(tcmalloc_minimal TCMALLOC)

You can then use this variable in your call to target_link_libraries and be sure you're linking against the static version 然后,您可以在调用target_link_libraries使用此变量,并确保链接到静态版本

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

Here you can see the result: 在这里你可以看到结果:

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

If you only need to support non-Windows platforms, then this old email from the CMake mailing list from one of the Kitware developers gives the simplest method. 如果您只需要支持非Windows平台,那么来自其中一个Kitware开发人员的CMake邮件列表中的旧电子邮件提供了最简单的方法。 In essence, use find_library() to find the location of the actual library, favouring static libraries over shared ones by listing them first in the names to look for. 实质上,使用find_library()来查找实际库的位置,通过首先在要查找的名称中列出静态库来支持静态库。 ie

find_library(TCMALLOC_LIB NAMES libtcmalloc_minimal.a tcmalloc_minimal)

You would then link to the library found in the usual way: 然后,您将链接到以常规方式找到的库:

target_link_libraries(${BIN_NAME} ${TCMALLOC_LIB})

You could get smarter about how you define the static library name if you need to support platforms where a static library is named something other than lib???.a . 如果您需要支持静态库被命名为lib???.a以外的平台,那么您可以更明智地定义如何定义静态库名称。 You would use CMAKE_STATIC_LIBRARY_PREFIX and CMAKE_STATIC_LIBRARY_SUFFIX variables for that. 您可以使用CMAKE_STATIC_LIBRARY_PREFIX和CMAKE_STATIC_LIBRARY_SUFFIX变量。

On Windows, the problem is that you cannot distinguish between a static library and the import library for a DLL, as discussed in this old issue in the Kitware bug tracker. 在Windows上,问题在于您无法区分静态库和DLL的导入库,如Kitware错误跟踪器中的旧版本中所述。 Both have the file extension .lib , so you can't use the extension to work out if a particular file is a static library or not, unlike Unix-based platforms where you can. 两者都具有文件扩展名.lib ,因此如果特定文件是静态库,则无法使用扩展来计算,与基于Unix的平台不同。

You have to set your CMAKE_FIND_LIBRARY_SUFFIXES variable in this manner: 您必须以这种方式设置CMAKE_FIND_LIBRARY_SUFFIXES变量:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a)

because in default CMAKE_FIND_LIBRARY_SUFFIXES there is also .so suffix (and it seems not searching in order of insertion). 因为在默认的CMAKE_FIND_LIBRARY_SUFFIXES中也有.so后缀(似乎没有按插入顺序搜索)。 In order to allow portability other suffixes should be added (see here for default values of CMAKE_FIND_LIBRARY_SUFFIXES on different platforms). 为了允许可移植性,应添加其他后缀(有关不同平台上的CMAKE_FIND_LIBRARY_SUFFIXES的默认值,请参见此处 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM