Macos 构建OSX应用程序包

Macos 构建OSX应用程序包,macos,gcc,otool,Macos,Gcc,Otool,假设我制作了一个没有使用Xcode的osX应用程序。在使用GCC编译之后,我得到了一个链接到其他几个库的可执行文件。其中一些库可能会再次动态链接到其他非标准系统库 是否有任何工具可以通过首先创建所需的目录结构,然后递归地复制/检查/修复链接来创建OSX应用程序包,以确保所有动态依赖项也在应用程序包中 我想我可以试着写这样的东西,但我想知道这样的东西是否已经存在。有一些开源工具可以帮助为特定环境(例如,基于Python的应用程序)构建带有依赖库的应用程序包。如果你找不到更通用的,也许你可以根据自己

假设我制作了一个没有使用Xcode的osX应用程序。在使用GCC编译之后,我得到了一个链接到其他几个库的可执行文件。其中一些库可能会再次动态链接到其他非标准系统库

是否有任何工具可以通过首先创建所需的目录结构,然后递归地复制/检查/修复链接来创建OSX应用程序包,以确保所有动态依赖项也在应用程序包中


我想我可以试着写这样的东西,但我想知道这样的东西是否已经存在。

有一些开源工具可以帮助为特定环境(例如,基于Python的应用程序)构建带有依赖库的应用程序包。如果你找不到更通用的,也许你可以根据自己的需要调整它。

最简单的解决方案是:创建一个Xcode项目,不做任何更改(即保留Xcode为你创建的简单单窗口应用程序),构建它,然后复制它为你创建的捆绑包。然后,编辑文件(尤其是Info.plist)以适合您的内容,并将您自己的二进制文件放入Contents/MacOS/目录。

在MacOSX上创建应用程序包有两种方法:简单方法和丑陋方法。

简单的方法就是使用XCode。 完成。

问题是有时候你不能。

就我而言,我正在构建一个可以构建其他应用程序的应用程序。 我不能假设用户已经安装了XCode。 我还使用它来构建我的应用程序所依赖的库。 在发布应用程序之前,我需要确保这些dylibs与应用程序捆绑在一起。

免责声明:我完全没有资格写这篇文章,所有的东西都是用英文写的 它是从苹果的文档中挑选出来的,将现有的应用程序和 反复试验。这对我来说很有效,但很可能是错的。请 如果您有任何更正,请发电子邮件给我。

首先要知道的是,应用程序包只是一个目录。
让我们检查一个假设的foo.app的结构。

foo.app/ 内容/ Info.plist 马科斯/ 福 资源/ foo.icns

Info.plist是一个普通的XML文件。 您可以使用文本编辑器或XCode附带的属性列表编辑器应用程序对其进行编辑。 (位于/Developer/Applications/Utilities/directory中)。

您需要包括的关键内容包括:

CbundLename-应用程序的名称。

Cbundleicon-一个图标文件,假定位于Contents/Resources目录中。 使用Icon Composer应用程序创建图标。(它也位于/Developer/Applications/Utilities/目录中) 您只需将png拖放到它的窗口中,就可以自动生成mip级别。

CbundleExecutable—假定位于Contents/MacOS/sub文件夹中的可执行文件的名称。

还有更多的选择,上面列出的只是最低限度的选择。 下面是一些苹果公司的文档 文件和 .

此外,这里还有一个示例Info.plist。

cfbundlegetingfostring 福 Cbundlexecutable 福 CbundleIdentifier com.your-company-name.www CFBundleName 福 循环流化床锅炉 foo.icns CbundleShortVersionString 0.01 CbundleInfo字典版本 6 CbundlePackageType 应用 IFMajorVersion 0 Ifminorvision 1.

在一个完美的世界中,您可以将可执行文件放入 目录/MacOS/dir,并完成。但是,如果你的应用程序有 非标准的动态库依赖项它不会工作。像Windows、MacOS 它有自己的特殊类型。

若您使用来构建链接所针对的库,DYLIB的位置将硬编码到您的可执行文件中。 如果您在DYLIB位于完全相同位置的计算机上运行应用程序,它将正常运行。 然而,大多数用户不会安装它们;当他们双击你的应用程序时,它就会崩溃。

在分发可执行文件之前,您需要收集它加载的所有dylib,并将它们复制到应用程序包中。 您还需要编辑可执行文件,以便它在正确的位置查找dylib。i、 e.您将它们复制到的位置。

手工编辑可执行文件听起来很危险,对吗? 幸运的是,有一些命令行工具可以提供帮助。

otool-L可执行文件名称

此命令将列出应用程序所依赖的所有动态库。 如果您看到任何不在System/Library或usr/lib文件夹中的内容,则需要将这些内容复制到应用程序包中。 将它们复制到/Contents/MacOS/文件夹中。 接下来,您需要编辑可执行文件以使用新的dylibs。

首先,您需要确保使用-headerpad\u max\u install\u names标志进行链接。 这只是确保如果新的动态库路径比前一个路径长,那么会有空间容纳它。

其次,使用install_name_工具更改每个动态库路径。

安装_name_工具-将现有的_路径_更改为_dylib@executable_path/blah.dylib executable_name

作为一个实际的例子,假设您的应用程序使用,而otool将其位置列为“/opt/local/lib/libSDL-1.2.0.dylib”。

首先将其复制到应用程序包中。

cp/opt/local/lib/libSDL-1.2.0.dylib foo.app/Contents/MacOS/

然后编辑可执行文件以使用新位置(注意:确保使用-headerpad\u max\u install\u names标志构建它)

安装_name_工具-change/opt/local/lib/libSDL-1.2.0.dylib@executable_path/libSDL-1.2.0.dylib foo.app/Contents/MacOS/foo

唷,我们差不多完了。 现在,当前工作目录有一个小问题。

启动应用程序时,当前目录将是应用程序所在位置上方的目录。 例如:如果将foo.app放在/Applications文件夹中,则启动应用程序时的当前目录将是/Applications文件夹。 不是您所期望的/Applications/foo.app/Contents/MacOS/。

你可以修改你的应用程序来解释t foo.app/ Contents/ Info.plist MacOS/ foo Resources/ foo.icns <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleGetInfoString</key> <string>Foo</string> <key>CFBundleExecutable</key> <string>foo</string> <key>CFBundleIdentifier</key> <string>com.your-company-name.www</string> <key>CFBundleName</key> <string>foo</string> <key>CFBundleIconFile</key> <string>foo.icns</string> <key>CFBundleShortVersionString</key> <string>0.01</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>IFMajorVersion</key> <integer>0</integer> <key>IFMinorVersion</key> <integer>1</integer> </dict> </plist> otool -L executable_name install_name_tool -change existing_path_to_dylib @executable_path/blah.dylib executable_name cp /opt/local/lib/libSDL-1.2.0.dylib foo.app/Contents/MacOS/ install_name_tool -change /opt/local/lib/libSDL-1.2.0.dylib @executable_path/libSDL-1.2.0.dylib foo.app/Contents/MacOS/foo #!/bin/bash cd "${0%/*}" ./foo
APPNAME=MyApp
APPBUNDLE=$(APPNAME).app
APPBUNDLECONTENTS=$(APPBUNDLE)/Contents
APPBUNDLEEXE=$(APPBUNDLECONTENTS)/MacOS
APPBUNDLERESOURCES=$(APPBUNDLECONTENTS)/Resources
APPBUNDLEICON=$(APPBUNDLECONTENTS)/Resources
appbundle: macosx/$(APPNAME).icns
    rm -rf $(APPBUNDLE)
    mkdir $(APPBUNDLE)
    mkdir $(APPBUNDLE)/Contents
    mkdir $(APPBUNDLE)/Contents/MacOS
    mkdir $(APPBUNDLE)/Contents/Resources
    cp macosx/Info.plist $(APPBUNDLECONTENTS)/
    cp macosx/PkgInfo $(APPBUNDLECONTENTS)/
    cp macosx/$(APPNAME).icns $(APPBUNDLEICON)/
    cp $(OUTFILE) $(APPBUNDLEEXE)/$(APPNAME)

macosx/$(APPNAME).icns: macosx/$(APPNAME)Icon.png
    rm -rf macosx/$(APPNAME).iconset
    mkdir macosx/$(APPNAME).iconset
    sips -z 16 16     macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_16x16.png
    sips -z 32 32     macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_16x16@2x.png
    sips -z 32 32     macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_32x32.png
    sips -z 64 64     macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_32x32@2x.png
    sips -z 128 128   macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_128x128.png
    sips -z 256 256   macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_128x128@2x.png
    sips -z 256 256   macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_256x256.png
    sips -z 512 512   macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_256x256@2x.png
    sips -z 512 512   macosx/$(APPNAME)Icon.png --out macosx/$(APPNAME).iconset/icon_512x512.png
    cp macosx/$(APPNAME)Icon.png macosx/$(APPNAME).iconset/icon_512x512@2x.png
    iconutil -c icns -o macosx/$(APPNAME).icns macosx/$(APPNAME).iconset
    rm -r macosx/$(APPNAME).iconset
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>MyApp</string>
    <key>CFBundleGetInfoString</key>
    <string>0.48.2, Copyright 2013 my company</string>
    <key>CFBundleIconFile</key>
    <string>MyApp.icns</string>
    <key>CFBundleIdentifier</key>
    <string>com.mycompany.MyApp</string>
    <key>CFBundleDocumentTypes</key>
    <array>
    </array>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>0.48.2</string>
    <key>CFBundleSignature</key>
    <string>MyAp</string>
    <key>CFBundleVersion</key>
    <string>0.48.2</string>
    <key>NSHumanReadableCopyright</key>
    <string>Copyright 2013 my company.</string>
    <key>LSMinimumSystemVersion</key>
    <string>10.3</string>
</dict>
</plist>
APPLMyAp