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

时间:2016-12-29 18:41:08

标签: c++ cmake ld rpath

情况

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

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

  • 所有共享对象库都可以使用相同的非标准库 文件夹(我需要它们)。

  • 由于某些原因,可以找到一些,但其他人不能。

我需要什么

  1. 找不到某些共享对象而找不到其他共享对象的原因。该项目非常庞大,包含许多CMake文件。我试图找到可以加载的库和不能加载的库之间的差异,但没有成功。任何帮助我到正确的地方的帮助都是受欢迎的。
  2. CMake中的一个解决方案,使其能够找到所有共享对象。
  3. 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)
    

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

    libboost_iostreams.so.1.55.0 => not found
    libboost_chrono.so.1.55.0 => not found
    

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

    已尝试解决方法

    以下是已成功运作的变通方法。但我真的对我需要什么部分中的两点感兴趣。

1 个答案:

答案 0 :(得分:0)

tldr; 。检查导入的库是否被导入为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"
)

但是,对于动态库,它是:

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"
)

在find_package模块模式脚本中,您可能会认为您正在导入静态库,而实际上发现的库是.so,因此它可能使用了不正确的目标属性。在配置模式下,这不太可能,因为在定义目标时它更加明确。虽然是模块模式(cmake / findXXX.cmake),但由于FIND_PACKAGE_HANDLE_STANDARD_ARGS _LIBRARIES变量,您经常在定义这些属性,很难说出要得到什么。您可以在搜索中使用libFoo.a来使其更明确或与CMAKE_FIND_LIBRARY_SUFFIXES一起玩。