如何在 Mac OS X (C++) 中使用 dylib
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4677044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use dylib in Mac OS X (C++)
提问by Alfred Zhong
I made an application (an executable) calling some dylib successfully, However, the dylib files and the executable are in different directory. I added the directory contains dylib files to the $PATH environment variable, however, it still doesn't load. I copy all the dylib files to the executable, the program finally runs. This confirms the dylib files have no problem. However, How can I tell the OS to find it? In windows, I just need to add the directory path contains dll files to $PATH. What do I need to do for Mac OS X? Thanks a lot!
我制作了一个应用程序(一个可执行文件)成功调用了一些 dylib,但是,dylib 文件和可执行文件位于不同的目录中。我将包含 dylib 文件的目录添加到 $PATH 环境变量中,但是,它仍然没有加载。我将所有 dylib 文件复制到可执行文件中,程序终于运行了。这证实了 dylib 文件没有问题。但是,我如何告诉操作系统找到它?在windows中,我只需要将包含dll文件的目录路径添加到$PATH。我需要为 Mac OS X 做什么?非常感谢!
回答by Akos Cz
After reading the link that Justin provided, I was successfully able to use the @executable_path
token to change my dylib install_name to point to the same dir where my executable is located.
阅读 Justin 提供的链接后,我成功地使用@executable_path
令牌将我的 dylib install_name 更改为指向我的可执行文件所在的同一目录。
@executable_pathAbsolute paths are annoying. Sometimes you want to embed a framework into an application instead of having to install the framework into /Library or a similar location.
The Mac's solution to this is @executable_path. This is a magic token that, when placed at the beginning of a library's install name, gets expanded to the path of the executable that's loading it, minus the last component. For example, let's say that Bar.app links against Foo.framework. If Bar.app is installed in /Applications, @executable_path will expand to /Applications/Bar.app/Contents/MacOS. If you intend to embed the framework in Contents/Frameworks, then you can just set Foo.framework's install name to @executable_path/../Frameworks/Foo.framework/Versions/A/Foo. The dynamic linker will expand that to /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo and will find the framework there.
http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
@executable_path绝对路径很烦人。有时您希望将框架嵌入到应用程序中,而不必将框架安装到 /Library 或类似位置。
Mac 对此的解决方案是@executable_path。这是一个神奇的标记,当放置在库安装名称的开头时,它会扩展为加载它的可执行文件的路径,减去最后一个组件。例如,假设 Bar.app 链接到 Foo.framework。如果 Bar.app 安装在 /Applications 中,@executable_path 将扩展到 /Applications/Bar.app/Contents/MacOS。如果您打算将框架嵌入 Contents/Frameworks,那么您只需将 Foo.framework 的安装名称设置为 @executable_path/../Frameworks/Foo.framework/Versions/A/Foo。动态链接器会将其扩展到 /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo 并将在那里找到框架。
http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
I will demonstrate with an example.
我将用一个例子来演示。
Let's say I have the following executable /opt/local/bin/convertand its dylibs are in /opt/local/lib. I want to copy it to another dir and have it load its dylibs from the same directory as where I copied the executable.
假设我有以下可执行文件/opt/local/bin/convert,其动态库位于/opt/local/lib 中。我想将它复制到另一个目录,并让它从与我复制可执行文件的目录相同的目录加载它的 dylib。
> mkdir ~/tmp/bin
> cp /opt/local/bin/convert ~/tmp/bin
Get a list of the executables dylibs
获取可执行文件 dylib 的列表
> otool -L ~/tmp/bin/convert
~/tmp/bin/convert:
/opt/local/lib/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/opt/local/lib/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)
/opt/local/lib/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)
/opt/local/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
/opt/local/lib/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)
/opt/local/lib/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)
/opt/local/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)
/opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)
...
I only care about the dylibs in the /opt/local/libdir, so we pull out only dylibs in /opt. I want to keep all other dylib references intact especially to /usr/lib/libSystemstuff.
我只关心/opt/local/lib目录中的 dylib,所以我们只提取/opt 中的dylib 。我想保持所有其他 dylib 引用完整无缺,尤其是对/usr/lib/libSystem 的东西。
> DYLIBS=`otool -L ~/tmp/bin/convert | grep "/opt" | awk -F' ' '{ print }'`
Copy all the dylibs that the executable references to the same dir where the executable has been copied to.
将可执行文件引用的所有 dylib 复制到可执行文件复制到的同一目录。
> for dylib in $DYLIBS; do cp $dylib ~/tmp/bin/; done;
Use the install_name_tool
to change the install name of all the dylibs we pulled out in the step above, and replace them by prepending the @executable_path
to the dylib name. This will make the dynamic linker look for the dylib in the same directory as where the executable is located.
使用install_name_tool
来更改我们在上述步骤中提取的所有 dylib 的安装名称,并通过@executable_path
在 dylib 名称前面加上来替换它们。这将使动态链接器在可执行文件所在的同一目录中查找 dylib。
> for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` ~/tmp/bin/convert; done;
Confirm that the install names have been changed and that libSystemis still pointing to /usr/lib/libSystem.
确认安装名称已更改并且libSystem仍指向/usr/lib/libSystem。
> otool -L ~/tmp/bin/convert
~/tmp/bin/convert:
@executable_path/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
@executable_path/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)
@executable_path/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)
@executable_path/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
@executable_path/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)
@executable_path/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)
@executable_path/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)
@executable_path/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)
...
回答by EmeryBerger
You need to set the DYLD_LIBRARY_PATH
environment variable.
您需要设置DYLD_LIBRARY_PATH
环境变量。
From the dyld man page:
从dyld 手册页:
This is a colon separated list of directories that contain libraries. The dynamic linker
searches these directories before it searches the default locations for libraries. It allows
you to test new versions of existing libraries.
For each library that a program uses, the dynamic linker looks for it in each directory in
DYLD_LIBRARY_PATH in turn. If it still can't find the library, it then searches DYLD_FALL-
BACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn.
回答by justin
many ways. maybe this will help:
很多方法。也许这会有所帮助:
http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
回答by Stephen Canon
If the dylib is in the place specified by the INSTALL_NAME of the library, it will Just Work*.
如果 dylib 位于库的 INSTALL_NAME 指定的位置,它就会正常工作*。
Otherwise, you can add the location of the dylib to DYLD_LIBRARY_PATH. You might want to read the dyld documentation.
否则,您可以将 dylib 的位置添加到 DYLD_LIBRARY_PATH。您可能需要阅读dyld 文档。
*) to be totally precise, it needs to be at DYLD_ROOT_PATH/INSTALL_NAME, but fussing with DYLD_ROOT_PATH is pretty rare.
*) 准确地说,它需要在 DYLD_ROOT_PATH/INSTALL_NAME,但对 DYLD_ROOT_PATH 大惊小怪是非常罕见的。