传递给链接器的动态库使用绝对路径,但是被相对路径加载?

4

我正在尝试构建和运行我的项目。我进行了构建,一切都很好,没有任何错误。然后当我尝试运行可执行文件时,我收到一个错误消息,说找不到一些动态库依赖项:

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可以使其正常工作,但我不想设置或导出它。我已经设置好我的存储库来构建所有依赖项并将它们放置在特定目录中,应该只需克隆和构建即可。
我的编译器版本是:
/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

1
otool -D lib_file 这条命令是用来查看库文件的名称。在某些情况下,它会显示完整路径,而在其他情况下则只会显示文件名。 - Francesco
实际上,libprotobuf 输出了自己的绝对路径,而 libgpr 只输出了它的文件名。 - alexgolec
1
然后,这就是问题所在。该库仅使用相对名称构建。您可以使用DYLD_LIBRARY_PATH,或者如果您无法访问库的源代码,则可以尝试使用install_name_tool进行一些操作。 - Francesco
这是一个很好的观察。但是,当我使用install_name_tool将安装名称更改为绝对路径并重新构建我的代码时,我得到了同样的问题。 - alexgolec
我不明白。你是自己编译这个库还是有人给了你? - Francesco
你尝试过使用install_name_tool -id new_absolute_file_name.dylib oldLib.dylib吗?我在一个库上尝试了一下,成功修改了库的名称。 - Francesco
1个回答

1
我最近遇到了这个问题。在构建dylib之后使用install_name_tool解决了问题; 然而,我正在使用的clang版本接受一个-install_name参数,让我重命名正在构建的dylib(我使用-install_name @rpath/<name>.dylib)。otool -D <name>.dylib确认了更正的名称。一旦主程序链接到这个新构建的dylib,otool -l <exe>就显示了正确更新的路径(在我的情况下是@rpath/<name>.dylib),并且在运行时正确找到了dylib。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接