首页 > 解决方案 > 针对错误版本的库的 CMake 链接

问题描述

我有一些依赖于 Protobuf v2.5 的 CMake 包,以及一个依赖于 Protobuf v3.4 的包。我在系统范围内安装了 v2.5 /usr,而 v3.4 仅在单个包中使用。因此,我将 v3.4 的标头放在3rdparty使用它的包内的子目录中,然后调用include_directories(3rdparty)我的 CMakeLists.txt 以便可以找到它。

至于共享库,v2.5 的 .so 文件存在于.so 中/usr/lib/x86_64-linux-gnu,我将 v3.4 的 .so 文件安装到/usr/lib. 简而言之,目录结构如下所示:

v2.5:
标题:/usr/include
库:/usr/lib/x86_64-linux-gnu

v3.4:
标题:<MY_PACKAGE_SRC_DIRECTORY>/3rdparty
库:/usr/lib

现在,当我尝试链接到 v3.4 时,问题就出现了。为了简化事情,我不使用任何 CMake 模块文件来查找 protobuf v3.4,而是/usr/lib/libprotobuf.so在创建目标时将硬编码路径添加到要链接的库列表中。但即便如此,当我运行时ldd my_target_executable,结果是:

libprotobuf.so.8 => /usr/lib/x86_64-linux-gnu/libprotobuf.so.8

这意味着它正在链接 v2.5 in 的库/usr/lib/x86_64-linux-gnu,即使我在构建此可执行文件时/usr/lib的调用中添加了指向正确 .so 文件的硬编码路径。target_link_libraries

值得注意的是,如果我删除 .so 中的文件/usr/lib/x86_64-linux-gnu,那么它会链接到 .so 中的正确文件/usr/lib,因此似乎出于某种原因,CMake 在/usr/lib/x86_64-linux-gnu使用我提供的库路径之前会进行搜索。如何更改此行为,或以任何其他方式解决此问题?

更新
v3.4 的库文件/usr/lib/x86_64-linux-gnu/libprotobuf.so是一个链接,/usr/lib/x86_64-linux-gnu/libprotobuf.so.14而该链接又是指向实际文件的链接/usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0

target_link_libraries现在,如果我将我提供的硬编码路径更改为/usr/lib/x86_64-linux-gnu/libprotobuf.so第二个符号链接 /usr/lib/x86_64-linux-gnu/libprotobuf.so.14或实际文件/usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0,那么我的可执行文件会正确链接到 v3.4。似乎提供的符号链接的名称对 CMake 的行为有一些影响。

标签: c++linuxcmakelinkershared-libraries

解决方案


这不是专门针对 cmake 的,而是使用 gcc 和共享库在 Linux 上的工作方式。

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

当您指定target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so)时,将链接设置为-lprotobuf. 在这种情况下,它应该只使用它首先找到的任何版本的库。

target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so.14)调整 cmake 生成的链接行以使用特定的库版本。这似乎告诉 gcc 链接到该版本,这将改变运行时和库搜索时发生的情况。

target_link_libraries

在某些情况下,CMake 可能会要求链接器搜索库(例如 /usr/lib/libfoo.so 变为 -lfoo),例如当检测到共享库没有 SONAME 字段时。有关另一种情况的讨论,请参见政策 CMP0060。


推荐阅读