如何分发带有依赖库的 Mac OS X?
我有一个计划(特别是我的 SO DevDays Countdown 应用挑战) 它依赖于几个动态库,即 libSDL、libSDL_ttf 等。我通过 MacPorts 将这些库安装在 /opt/local/lib
下,许多人不会安装这些库(有些人可能安装了它们,但没有安装在该位置)。
如何分发我的程序,以便没有安装这些库的人可以开箱即用地运行它?显然,我必须分发各种 .dylib
文件,但这样做是不够的。动态加载器仍然会在我安装的位置查找安装的库。有没有办法告诉动态加载器在可执行文件的当前目录中查找,就像 Windows 对 DLL 所做的那样?人们不必修改任何环境变量(例如DYLD_LIBRARY_PATH
),因为我再次希望它开箱即用。
I have a program (specifically my entry for the SO DevDays Countdown app challenge) which relies on several dynamic libraries, namely libSDL, libSDL_ttf, and others. I have these libraries installed under /opt/local/lib
via MacPorts, and many people won't have these installed (and some might have them installed, but not at that location).
How do I distribute my program so that people without these libraries installed can run it out-of-the-box? Obviously I'll have to distribute the various .dylib
files, but doing this is insufficient. The dynamic loader still looks for the libraries installed at the locations I have them installed at. Is there a way to tell the dynamic loader to look in the current directory of the executable, like what Windows does with DLLs? People shouldn't have to modify any environment variables (e.g. DYLD_LIBRARY_PATH
), since again I want this to work out-of-the-box.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
基本方法是将它们放在 .app 捆绑包中。然后,您将修改链接器查找共享库的位置以包含该共享库。
步骤如下:
为您的目标创建一个新的复制文件构建阶段,将这些文件复制到 .app 捆绑包的 Frameworks 目录中。
编辑构建配置设置“运行路径搜索路径”以包含
@executable_path/../Frameworks
如果您使用这些更改构建可执行文件,然后查看,您应该发现 dylib 存在于
Foo.app/Contents/Framework
目录中并正在运行otool -L Foo.app/Contents/MacOS/Foo
应该为这些 dylib 生成并以 @rpath 为前缀的条目。从这个 Cocoabuilder 帖子:
一般来说,
@loader_path
优于@executable_path
,因为它允许嵌入式框架在可执行文件和捆绑包中工作,
插件或子框架。唯一的缺点是
@loader_path
需要 10.4 或更高版本。如果您使用的是 10.5 或更高版本,
@rpath
是偶数比
@loader_path
更好。The basic approach to this is to ship them in the .app bundle. You'll then modify the location the linker looks for shared libraries to include this.
The steps are:
Create a new copy files build phase to your target that copies those files into the Frameworks directory of the .app bundle.
Edit the build configuration setting "Runpath Search Paths" to include
@executable_path/../Frameworks
If you build your executable with these changes and then look, you should find that the dylibs exist in the
Foo.app/Contents/Framework
directory and runningotool -L Foo.app/Contents/MacOS/Foo
should yield and entry prefixed by @rpath for those dylibs.From this Cocoabuilder post:
In general,
@loader_path
is preferred over@executable_path
, as itallows embedded frameworks to work in both an executable and a bundle,
plugin, or sub-framework. The only downside is that
@loader_path
requires 10.4 or newer. If you're on 10.5 or newer,
@rpath
is evenbetter than
@loader_path
.正如您提到的,您没有使用 Xcode,所以这有点困难。以下是按照我的偏好顺序排列的选项:
切换到 Xcode。使用框架。 SDL 库已经可以作为框架使用,而且我已经见过不少在应用程序包中包含 libsdl.framework 的商业游戏。
使用框架,但保留 Makefile。下载 SDL 库的框架版本(或自己构建它们),并使用 -framework 链接器标志链接它们。随您的应用程序分发或不分发框架,并告诉您的用户将它们放入 ~/Library/Frameworks 或 /Library/Frameworks 中。我不会为此使用安装程序。
针对 SDL 的静态链接。在 Makefile 中,您必须列出静态库的路径,而不是使用 -l 标志,例如,运行“ld blah blah /opt/local/lib/libsdl.a”。我不知道如何告诉 -l 更喜欢静态而不是共享库,相信我,我已经看过了。
As you mentioned you're not using Xcode, so it's a bit difficult. Here are options in my order of preference:
Switch to Xcode. Use frameworks. The SDL libraries are available as frameworks already, and I've seen more than a couple commercial games with a libsdl.framework inside the app bundle.
Use frameworks, but keep your Makefiles. Download the framework versions of your SDL libraries (or build them yourself), and link with them with the -framework linker flag. Distribute the frameworks with your app or don't, and tell your users to put them in either ~/Library/Frameworks or in /Library/Frameworks. I wouldn't bother with an installer for this.
Statically link against SDL. In the Makefile, you'll have to list the path of the static libraries rather than use the -l flag, e.g., you run "ld blah blah /opt/local/lib/libsdl.a". There is no way that I know to tell -l to prefer static over shared libraries, and believe me, I've looked.
静态链接库。
Statically link the libraries.