install_name_tool 更新可执行文件以在 Mac OS X 中搜索 dylib
Posted
技术标签:
【中文标题】install_name_tool 更新可执行文件以在 Mac OS X 中搜索 dylib【英文标题】:install_name_tool to update a executable to search for dylib in Mac OS X 【发布时间】:2016-03-03 16:11:11 【问题描述】:我有一个动态库 libtest.dylib,安装在 /PATH/lib
中,还有一个执行二进制文件 myapp,它使用安装在 /PATH/bin
中的 dylib。
我可以运行myapp
来找到dylib,如下(Is it OK to use DYLD_LIBRARY_PATH on Mac OS X? And, what's the dynamic library search algorithm with it?):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
我想我可以使用install_name_tool
来更新库和可执行文件,以便可以使用 rpath 找到该库。我使用了这篇文章中的提示 - How can I specify the rpath in a dylib?。
在 lib 中,我执行了这个命令来添加 rpath。
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib
在 bin 中,我执行了install_name_tool -add_rpath "@executable_path/../lib/" myapp
。
但是,当我在bin
目录中执行myapp
时,我收到了错误消息。
dyld: Library not loaded: libtest.dylib
Referenced from: /PATH/bin/./myapp
Reason: image not found
Trace/BPT trap: 5
otool -l myapp
显示 rpath 在 myapp 中已正确更新。
Load command 16
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
libtest.dylib 也是如此
Load command 13
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
可能出了什么问题?
添加
当然,我可以在编译和链接时使用cc -install_name
,但我想知道如何在修改生成的dylib 和执行二进制文件时做同样的事情。
来自库:
cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c
或者,install_name 可以使用@rpath:
cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c
从垃圾箱:
cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib
或者只有一行:
cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib
【问题讨论】:
【参考方案1】:来自otool -l
,我分析了应该从原始库和二进制文件中添加或修改的内容。
Dylib
变化在 id:
Load command 2 <-- OLD
cmd LC_ID_DYLIB
cmdsize 40
name libtest.dylib (offset 24)
time stamp 1 Wed Dec 31 18:00:01 1969
Load command 2 <-- NEW
cmd LC_ID_DYLIB
cmdsize 64
name @loader_path/../lib/libtest.dylib (offset 24)
这是完成更改的命令:
install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib
或者使用rpath:
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
可执行文件
有两个变化:rpath和load_dylib
Load command 12 <-- OLD
cmd LC_LOAD_DYLIB
cmdsize 40
name libtest.dylib (offset 24)
Load command 12 <-- NEW
cmd LC_LOAD_DYLIB
cmdsize 64
name @loader_path/../lib/libtest.dylib (offset 24)
这是完成更改的命令
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp
我还需要添加 rpath
Load command 14
cmd LC_RPATH
cmdsize 32
path @loader_path/../lib (offset 12)
这是完成添加的命令:
install_name_tool -add_rpath "@loader_path/../lib" myapp
想法
二进制文件试图找到库,它从install_name_tool -add_rpath "@loader_path/../lib" myapp
知道它的位置。它加载库,库的 id 是@rpath/libtest.dylib
,其中@rpath
在可执行二进制文件中设置为@loader_path/../lib
以进行匹配。
参考
Can you please help me understand how Mach-O libraries work in Mac Os X?Cmake
在使用 CMake 时,我们可以通过在 CMakeLists.txt 文件中添加以下内容来自动化该过程。
图书馆应该加上id。
# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
PROPERTIES BUILD_WITH_INSTALL_RPATH 1
INSTALL_NAME_DIR "@rpath"
)
可执行文件
应该指定rpath:
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")
【讨论】:
似乎 dylib 中的属性在运行时并不重要。它们仅在构建时用于将属性从 dylib 复制到可执行文件。对于已经有一个链接到 dylib 的可执行文件但需要更改路径的情况,只需编辑可执行文件以设置 LC_LOAD_DYLIB 和可选的 LC_RPATH 就足够了。仅当第一个包含 @rpath 时才需要第二个。以上是关于install_name_tool 更新可执行文件以在 Mac OS X 中搜索 dylib的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 install_name_tool:无法在 xcode 10.2 中打开文件
MACOS上install_name_tool有时无法改变rpath
install_name_tool 格式错误的对象(加载命令 23 cmdsize 为零) - Mac OS X Yosemite