是否可以让 clang link dylib 相对而不使用 install_name_tool?
Is it possible to have clang++ link dylib's relatively and not use install_name_tool?
总结
当 link 使用 dylib 执行可执行文件时,install_name_tool
是使 dylib 路径相对于可执行文件的唯一方法,或者在 clang 的 [=71 中是否有这样做的方法=]步数?
设置
给定以下项目结构:
- Project Root
| compile.sh
- lib_src
| myprint.cpp
| myprint.h
- main_src
| main.cpp
使用这些文件:https://gist.github.com/JohannesMP/8fa140b60b8ffeb2cae0
运行 compile.sh
(为简单起见,此处使用而不是 make 文件)生成以下文件:
- Project Root
| main (a unix executable linked to myprint.dylib)
| myprint.dylib (a dynamic library that main uses)
运行 带有 ./main
的程序在 cd
进入项目时工作正常,但试图从其他任何地方 运行 它,例如简单地加倍单击它,将导致以下错误:
dyld: Library not loaded: myprint.dylib
Referenced from: /Users/Jo/Sandbox/libtest/main
Reason: image not found
Trace/BPT trap: 5
当使用 otool
检查 main 时,我可以看到这是因为 myprint.dylib 的路径未根据可执行文件定义:
$ otool -L main
main:
myprint.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
常规修复
据我所知,建议的解决方法是使用 install_name_tool -change
并修改路径以使用 @executable_path
:
install_name_tool -change myprint.dylib @executable_path/myprint.dylib main
问题
虽然上面的修复显然有效,但对我来说似乎有点不直观,因为没有办法告诉 clang 只是 link main
已经使用了 [=23] =] 开始。似乎很奇怪,当编译一个包含任意数量的 dylib 的程序时,必须对每个 dylib 都这样做。
真的只有这样吗?这是 cmake 和 xcode 在幕后所做的吗?为什么我们不能默认 clang++
link 相对而不是绝对?
我找到了一些可以简化该过程的工具,例如 mac dylib bundler,但我很好奇是否有人对 为什么 有任何见解这样做。
TL;DR
有没有办法 change just this line 避免 运行 install_name_tool -change
?
确实可以:
编译我的库时,我将其 install_name
设置为 @rpath
:
clang++ -dynamiclib lib_src/myprint.cpp -o myprint.dylib -install_name @rpath/myprint.dylib
然后在编译可执行文件时,我将 rpath
设置为 @executable_path
,这可以一步完成:
clang++ main_src/main.cpp -o main -I ./lib_src myprint.dylib -rpath @executable_path
有关 @rpath
和 @executable_path
的详细说明,请查看此 wiki:https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath
总结
当 link 使用 dylib 执行可执行文件时,install_name_tool
是使 dylib 路径相对于可执行文件的唯一方法,或者在 clang 的 [=71 中是否有这样做的方法=]步数?
设置
给定以下项目结构:
- Project Root
| compile.sh
- lib_src
| myprint.cpp
| myprint.h
- main_src
| main.cpp
使用这些文件:https://gist.github.com/JohannesMP/8fa140b60b8ffeb2cae0
运行 compile.sh
(为简单起见,此处使用而不是 make 文件)生成以下文件:
- Project Root
| main (a unix executable linked to myprint.dylib)
| myprint.dylib (a dynamic library that main uses)
运行 带有 ./main
的程序在 cd
进入项目时工作正常,但试图从其他任何地方 运行 它,例如简单地加倍单击它,将导致以下错误:
dyld: Library not loaded: myprint.dylib
Referenced from: /Users/Jo/Sandbox/libtest/main
Reason: image not found
Trace/BPT trap: 5
当使用 otool
检查 main 时,我可以看到这是因为 myprint.dylib 的路径未根据可执行文件定义:
$ otool -L main
main:
myprint.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
常规修复
据我所知,建议的解决方法是使用 install_name_tool -change
并修改路径以使用 @executable_path
:
install_name_tool -change myprint.dylib @executable_path/myprint.dylib main
问题
虽然上面的修复显然有效,但对我来说似乎有点不直观,因为没有办法告诉 clang 只是 link main
已经使用了 [=23] =] 开始。似乎很奇怪,当编译一个包含任意数量的 dylib 的程序时,必须对每个 dylib 都这样做。
真的只有这样吗?这是 cmake 和 xcode 在幕后所做的吗?为什么我们不能默认 clang++
link 相对而不是绝对?
我找到了一些可以简化该过程的工具,例如 mac dylib bundler,但我很好奇是否有人对 为什么 有任何见解这样做。
TL;DR
有没有办法 change just this line 避免 运行 install_name_tool -change
?
确实可以:
编译我的库时,我将其 install_name
设置为 @rpath
:
clang++ -dynamiclib lib_src/myprint.cpp -o myprint.dylib -install_name @rpath/myprint.dylib
然后在编译可执行文件时,我将 rpath
设置为 @executable_path
,这可以一步完成:
clang++ main_src/main.cpp -o main -I ./lib_src myprint.dylib -rpath @executable_path
有关 @rpath
和 @executable_path
的详细说明,请查看此 wiki:https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath