是否可以告诉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
?
答案 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)。