使用 CMake 时如何避免“无法打开共享对象文件”?

mz1*_*000 5 c++ rpath cmake ld

情况

  • 我的项目使用 CMake 并且在 Ubuntu 16.04 上编译没有问题。

  • 启动编译的应用程序时,我收到消息无法打开共享对象文件

  • 所有共享对象库都可以在同一个非标准文件夹中使用(我在那里需要它们)。

  • 由于某种原因,有些可以找到,但另一些则找不到。

我需要的

  1. 为什么有的共享对象能找到,有的却找不到。该项目相当大,有很多 CMake 文件。我试图找出可以加载的库和不能加载的库之间的差异,但没有成功。欢迎任何帮助我找到正确的地方。
  2. CMake 中的一个解决方案,使其能够找到所有共享对象。

LDD

ldd输出显示大多数共享对象都可以找到这里有些例子:

libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f2ed1fa0000)
libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f96af1f5000)
libboost_program_options.so.1.55.0 => /path/to/libs/boost/lib/libboost_program_options.so.1.55.0 (0x00007f96aef85000)
libboost_system.so.1.55.0 => /path/to/libs/boost/lib/libboost_system.so.1.55.0 (0x00007f96aed80000)
Run Code Online (Sandbox Code Playgroud)

由于某种原因,其他一些无法找到。例如:

libboost_iostreams.so.1.55.0 => not found
libboost_chrono.so.1.55.0 => not found
Run Code Online (Sandbox Code Playgroud)

还有其他非 boost 库显示相同的行为,但为了简单起见,我只展示 boost 示例。

已经尝试过的解决方法

以下是已经成功运行的解决方法。但我对“我需要什么”部分中的两点非常感兴趣。

joh*_*003 0

太棒了;检查导入的库是否作为 SHARED 或 UNKNOWN 而不是 STATIC 导入,并且具有 IMPORTED_SONAME 属性。

您应该检查您链接的库是如何导入的。

我分析了静态和动态库的一些配置模式导出目标,它们为目标设置的属性略有不同。

例如,对于 zlib,这是静态库的版本:

add_library(ZLIB::zlibstatic STATIC IMPORTED)
set_target_properties(ZLIB::zlibstatic PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C"
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.a"
)
Run Code Online (Sandbox Code Playgroud)

但是,对于动态库来说:

add_library(ZLIB::zlib SHARED IMPORTED)
set_target_properties(ZLIB::zlib PROPERTIES
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.so.1.2.11"
  IMPORTED_SONAME_NOCONFIG "libz.so.1"
)
Run Code Online (Sandbox Code Playgroud)

在 find_package 模块模式脚本中,您可能认为正在导入静态库,而实际上找到的库是 .so,因此它可能使用不正确的目标属性。在配置模式下,这不太可能,因为定义目标时它更加明确。不过,在模块模式(cmake/findXXX.cmake)中,您经常将这些属性定义为FIND_PACKAGE_HANDLE_STANDARD_ARGS_LIBRARIES 变量的结果,并且很难知道您将得到什么。您可以在搜索中使用 libFoo.a 来更明确或使用 CMAKE_FIND_LIBRARY_SUFFIXES。