【问题标题】:Linking shared libraries in same directory链接同一目录中的共享库
【发布时间】:2015-02-11 10:09:23
【问题描述】:

我正在使用 CMake 构建两个共享库(.so 文件)。它们被构建到单独的目录中,但在安装步骤中,它们会将副本复制到同一目录中。其中一个与另一个链接。两者都是从另一个进程动态加载的。

第一个问题是显然 CMake 没有在 OS X 上的 .so 文件上设置 rpath(未在其他平台上测试)。在CMakeLists.txt我有

set(CMAKE_INSTALL_PREFIX ../dist)
set(MACOSX_RPATH YES)
set(INSTALL_NAME_DIR YES)

两个库的 CMakeLists.txt 文件被包含使用

add_subdirectory(./a "${CMAKE_BINARY_DIR}/a")
add_subdirectory(./b "${CMAKE_BINARY_DIR}/b")

但是在生成的.so 文件上运行otool -l 显示没有LC_RPATH 条目。

另外,需要在 RPath(a)中设置哪个路径,以便当链接器加载 a.so 时,它可以找到位于同一目录 (dist/) 中的 b.so。加载a 的可执行文件位于不同的位置。

我尝试了@executable_path/@executable_path/../@origin/../,但似乎都没有。

【问题讨论】:

    标签: macos linker cmake makefile dyld


    【解决方案1】:

    第一个问题是显然 CMake 没有设置 rpath

    默认情况下,cmake 会在构建目录中为目标设置 rpath(参见 project):

    > cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON
    > cmake --build _builds
    > ls _builds/foo _builds/liba.dylib 
      _builds/foo
      _builds/liba.dylib
    > otool -L _builds/foo 
    _builds/foo:
      @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
      ...
    > otool -l _builds/foo | grep LC_RPATH -A2
          cmd LC_RPATH
      cmdsize 64
         path /.../_builds (offset 12)
    

    即如果您从目录_builds 运行它,库将正确加载:

    > ./_builds/foo
    a: 42
    

    但是在生成的 .so 文件上运行 otool -l 显示没有 LC_RPATH 条目。

    另外,需要在 RPath 中设置哪个路径

    我已经尝试过@executable_path/、@executable_path/../、@origin/../,但似乎都不起作用。

    这取决于您要安装库和可执行文件的位置。例如,如果 目标目录是一样的,你可以设置@executable_path:

    set(CMAKE_INSTALL_RPATH "@executable_path")
    install(TARGETS foo a DESTINATION bin)
    

    参见示例project

    > cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=_install
    > cmake --build _builds --target install
    > otool -L _install/bin/foo 
    _install/bin/foo:
      @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
      ...
    > otool -l _install/bin/foo | grep LC_RPATH -A2
          cmd LC_RPATH
      cmdsize 32
         path @executable_path (offset 12)
    

    您可以测试该库是否会从_install 正确加载:

    > ./_install/bin/foo
    a: 42
    

    信息

    【讨论】:

    • 它适用于这些设置,但问题似乎是当我使用工具链文件 (-DCMAKE_TOOLCHAIN_FILE=...) 设置备用编译器时,它不再添加 RPaths,并且不再预先添加 @987654333 @ 到安装名称。通过使用-DCMAKE_CXX_COMPILER 选项解决了它。
    • @tmlen 您的工具链文件可能有问题。通常通过工具链设置编译器没有问题。
    • @tmlen 我不知道原因,但似乎set(CMAKE_SYSTEM_NAME Darwin) 是这里的罪魁祸首。可能在设置CMAKE_SYSTEM_NAME 的函数中完成了 RPATH 调整,所以如果你强制这个变量,一些代码将被跳过。
    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多