CMake 动态链接 `/usr/local/lib` 中的 `.a` 文件

3

我希望能够静态编译我的程序与另一个静态库进行链接,这个例子中我使用的是zeromq。以下是我的CMakeLists.txt文件:

cmake_minimum_required(VERSION 2.6)
add_executable( test test.cpp )
find_library(ZMQ NAMES libzmq.a)
message(STATUS ${ZMQ})
target_link_libraries( test ${ZMQ} )

当我运行 mkdir build && cd build && cmake .. 命令时,它会找到 .a 文件。
-- /usr/local/lib/libzmq.a

然而,如果我检查 link.txt 文件,库是动态链接的:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o \
    -o test -rdynamic /usr/local/lib/libzmq.a

奇怪的是,如果我将文件移动到另一个目录,比如 /usr/lib,然后再次运行 cmake ..,它就会找到库的新路径:

-- /usr/lib/libzmq.a

但现在它神奇地变成了静态链接:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o \
    -o test -rdynamic -Wl,-Bstatic -lzmq -Wl,-Bdynamic

同样的情况也适用于我链接到的其他库。

为什么我所有的库都在/usr/local/lib中被动态链接?

3个回答

8

您不应直接使用路径,而是创建导入的目标,这样您就可以明确声明它为静态:

cmake_minimum_required(VERSION 2.6)
add_executable( test test.cpp )

find_library(zmq_location NAMES libzmq.a)
message(STATUS ${zmq_location})

add_library(zmq STATIC IMPORTED)
set_target_properties(zmq PROPERTIES IMPORTED_LOCATION ${zmq_location})

target_link_libraries( test zmq )

这可能导致库表面上看起来是动态链接的情况,但cmake源代码有答案

如果目标不是静态库,请确保链接类型为共享。这是因为动态模式链接可以处理共享和静态库,但静态模式只能处理静态库。如果前一个用户项目将链接类型更改为静态,我们需要确保它回到共享状态。

基本上,它让链接器处理在动态模式下检测到库是静态的情况。

find_library返回的路径肯定是正确的。我尝试使用您更新后的cmake文件,现在它在两个位置都显示为动态。我还升级了cmake到最新版本,但问题仍然存在。 - morloch

1
我的最初问题是关于/usr/local/lib/usr/lib之间的区别,答案是,默认情况下,/usr/local/lib不是隐式链接目录之一。因此,一个快速修复方法是在配置中包含以下行:
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES /usr/local/lib ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})

然而,正如其他答案所指出的那样,直接引用文件并不可行,应该使用add_library

你需要用双引号将 CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES 的值包裹起来,以确保 /usr/local/lib 和旧值之间的空格得以保留。 - Shukant Pal

0

这是我的演示:

find_library(VLQ_LIB NAMES vlq-shared PATHS /usr/local/lib/ REQUIRED)
find_path(VLQ_HEADER vlq.hpp /usr/local/include)
target_link_libraries(myproj PUBLIC VLQ_LIB)
target_include_directories(myproj PUBLIC VLQ_HEADER)

但是在运行时,您仍然需要将共享库复制到/lib/文件夹中,对于静态库,您可以将其保留在/usr/lib下面。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接