作为由相对路径加载的绝对路径传递给链接器的动态库?

Posted

技术标签:

【中文标题】作为由相对路径加载的绝对路径传递给链接器的动态库?【英文标题】:Dynamic libraries passed to the linker as absolute paths being loaded by relative path? 【发布时间】:2015-12-22 21:11:02 【问题描述】:

我正在尝试构建和运行我正在处理的项目。我继续建造,一切都很棒,没有任何错误。然后,当我尝试运行可执行文件时,我收到一条错误消息,提示找不到某些动态库依赖项:

dyld: Library not loaded: libgpr.dylib
  Referenced from: ./test-exec
  Reason: image not found
Trace/BPT trap: 5

有趣。 otool -l 报告什么?

... snip ...
Load command 11
       cmd LC_MAIN
   cmdsize 24
  entryoff 1247184
 stacksize 0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 104
         name /abs/path/to/libprotobuf.10.dylib (offset 24) <--- The same path as passed to the linker
   time stamp 2 Wed Dec 31 19:00:02 1969
      current version 11.0.0
compatibility version 11.0.0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libgpr.dylib (offset 24)     <--- Note the local path
   time stamp 2 Wed Dec 31 19:00:02 1969
      current version 0.0.0
compatibility version 0.0.0

什么给了?我的构建调用是(经过一些清理后),由 CMake 发出:

编译(为了可读性而换行)

cd /path/to/project && /path/to/c++ 
   -Wno-inconsistent-missing-override -g -fPIE 
-I/path/to/project -I/googletest/headers 
-I/googlemock/headers 
-I/path/to/project/usr/include 
-I/include 
-I/path/to/jni/Contents/Home/include
-I/path/to/jni/Home/include/darwin
-std=gnu++11 -o test-exec.o -c
/path/to/project/test-exec.cc

链接:

cd /path/to/project && /usr/local/Cellar/cmake/3.2.2/bin/cmake -E cmake_link_script CMakeFiles/test-exec.dir/link.txt --verbose=1
/path/to/c++   
-Wno-inconsistent-missing-override -g 
-Wl,-search_paths_first
-Wl,-headerpad_max_install_names  
test-exec.o  -o test-exec
/path/to/libprotobuf.dylib 
/path/to/libgpr.dylib
/path/to/libgrpc.dylib
/path/to/libgrpc++.dylib
../../dep1.a
../../dep2.a
/path/to/libgmock.a
/path/to/libgmock_main.a 
/path/to/libgtest_main.a

据我所知,libprotobuf.dyliblibgpr.dylib 在链接阶段都作为绝对路径传入。为什么libprotobuf.dylib 是通过绝对路径而不是libgpr.dylib 加载的?

对于它的价值,设置DYLD_LIBRARY_PATH 使其工作,但我不想设置它或导出它。我已经设置了我的 repo 来构建所有依赖项并将它们放置到一个特定的目录中,它应该只是克隆和构建。

我的编译器版本是:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ --version
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

【问题讨论】:

otool -D lib_file 它说什么?这将打印库的名称。我希望一种情况下具有完整路径,另一种情况下只有文件名 确实,libprotobuf 输出到它自己的绝对路径,而libgpr 只输出它的文件名。 那么,这就是问题所在。该库仅使用相对名称构建。你可以使用DYLD_LIBRARY_PATH,或者如果你无权访问库的源代码,你可以尝试使用install_name_tool 这是一个很好的观察。但是,当我使用 install_name_tool 将安装名称更改为绝对路径并重建我的代码时,我遇到了同样的问题。 我不明白。你编译这个库还是有人给你的? 【参考方案1】:

我最近遇到了这个问题。在构建 dylib 后使用 install_name_tool 解决了问题;但是,我正在使用的 clang 版本接受一个 -install_name 参数,它可以让我重命名我正在构建的 dylib(我使用了 -install_name @rpath/&lt;name&gt;.dylib)。 otool -D &lt;name&gt;.dylib 确认更正后的名称。一旦主程序与这个新构建的 dylib 链接,otool -l &lt;exe&gt; 会显示正确更新的路径(在我的例子中是@rpath/&lt;name&gt;.dylib),并且在运行时正确找到了 dylib。

【讨论】:

以上是关于作为由相对路径加载的绝对路径传递给链接器的动态库?的主要内容,如果未能解决你的问题,请参考以下文章

java 加载动态链接库怎么使用相对路径

cmake中target_link_libraries()使用问题动态库使用绝对路径没问题,但是使用相对路径就矬了?

相对路径与绝对路径

动态链接--so的搜索过程

使用rpath解决指定动态库链接目录问题

在 Qt Creator 中加载具有相对路径的文件