[英]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.