StéphaneSudre有一个非常有趣的应用程序,它可以为您完成所有这些工作,可编写脚本/支持从命令行进行构建,具有非常漂亮的GUI,并且免费。可悲的是:它被称为“包裹”,因此无法在Google中找到。
注意:这仅适用于OS X Installer软件包,提交给Mac App Store的软件包遵循不同的规则。
由于Mountain Lion的Gatekeeper,我最终不得不将我的PackageMaker构建脚本带到谷仓后面进行拍摄。 PackageMaker已从Xcode中删除,并移至“ Xcode辅助工具”中,因此希望很快会被忘记。
问题是如何使用pkgbuild
,productbuild
和pkgutil
替换它?
我们的示例项目有两个构建目标:HelloWorld.app和Helper.app。我们为每一个制作一个component package并将它们组合成一个product archive。
。A component package包含要由OS X安装程序安装的有效负载。虽然是一个组成部分软件包可以单独安装,通常包含在产品归档中。
成功完成“构建和存档”后,在终端中打开$ BUILT_PRODUCTS_DIR。
$ cd ~/Library/Developer/Xcode/DerivedData/.../InstallationBuildProductsLocation
$ pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
$ pkgbuild --analyze --root ./Helper.app HelperAppComponents.plist
这为我们提供了component-plist,您可以在"Component Property List"部分中找到值说明。 pkgbuild -root生成component packages,如果不需要更改任何默认属性,则可以在以下命令中省略-component-plist参数。
productbuild --synthesize产生Distribution Definition。
$ pkgbuild --root ./HelloWorld.app \
--component-plist HelloWorldAppComponents.plist \
HelloWorld.pkg
$ pkgbuild --root ./Helper.app \
--component-plist HelperAppComponents.plist \
Helper.pkg
$ productbuild --synthesize \
--package HelloWorld.pkg --package Helper.pkg \
Distribution.xml
在Distribution.xml中,您可以更改标题,背景,欢迎词,自述文件,许可证等。使用此命令将组件包和分发定义转换为产品归档:
$ productbuild --distribution ./Distribution.xml \
--package-path . \
./Installer.pkg
我建议查看iTunes Installers Distribution.xml,以了解可能的情况。您可以使用以下方法解压缩“ Install iTunes.pkg”:
$ pkgutil --expand "Install iTunes.pkg" "Install iTunes"
我通常在我的项目中有一个名为Package的文件夹,其中包含Distribution.xml,component-plists,资源和脚本之类的东西。
添加名为“生成程序包”的运行脚本构建阶段,它设置为仅在安装时运行脚本] ::
生成软件包后不必更改软件包,则可以摆脱VERSION=$(defaults read "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/Contents/Info" CFBundleVersion) PACKAGE_NAME=`echo "$PRODUCT_NAME" | sed "s/ /_/g"` TMP1_ARCHIVE="${BUILT_PRODUCTS_DIR}/$PACKAGE_NAME-tmp1.pkg" TMP2_ARCHIVE="${BUILT_PRODUCTS_DIR}/$PACKAGE_NAME-tmp2" TMP3_ARCHIVE="${BUILT_PRODUCTS_DIR}/$PACKAGE_NAME-tmp3.pkg" ARCHIVE_FILENAME="${BUILT_PRODUCTS_DIR}/${PACKAGE_NAME}.pkg" pkgbuild --root "${INSTALL_ROOT}" \ --component-plist "./Package/HelloWorldAppComponents.plist" \ --scripts "./Package/Scripts" \ --identifier "com.test.pkg.HelloWorld" \ --version "$VERSION" \ --install-location "/" \ "${BUILT_PRODUCTS_DIR}/HelloWorld.pkg" pkgbuild --root "${BUILT_PRODUCTS_DIR}/Helper.app" \ --component-plist "./Package/HelperAppComponents.plist" \ --identifier "com.test.pkg.Helper" \ --version "$VERSION" \ --install-location "/" \ "${BUILT_PRODUCTS_DIR}/Helper.pkg" productbuild --distribution "./Package/Distribution.xml" \ --package-path "${BUILT_PRODUCTS_DIR}" \ --resources "./Package/Resources" \ "${TMP1_ARCHIVE}" pkgutil --expand "${TMP1_ARCHIVE}" "${TMP2_ARCHIVE}" # Patches and Workarounds pkgutil --flatten "${TMP2_ARCHIVE}" "${TMP3_ARCHIVE}" productsign --sign "Developer ID Installer: John Doe" \ "${TMP3_ARCHIVE}" "${ARCHIVE_FILENAME}"
如果使用productbuild
pkgutil --expand
和pkgutil --flatten
步骤。您也可以在productbuild上使用-sign参数,而不是运行productsign。程序包使用Developer ID Installer证书签名,可以从Developer Certificate Utility下载。
它们的签名是通过pkgbuild
,productbuild或productsign的--sign "Developer ID Installer: John Doe"
参数完成的。注意,如果要使用productbuild创建已签名的产品归档
,则没有理由对组件包进行签名。要将某些内容复制到Xcode存档中,我们不能使用Run Script Build Phase。为此,我们需要使用“方案动作”。
编辑方案并展开存档。然后单击后操作并添加New Run Script Action
:在Xcode 6中:
#!/bin/bash PACKAGES="${ARCHIVE_PATH}/Packages" PACKAGE_NAME=`echo "$PRODUCT_NAME" | sed "s/ /_/g"` ARCHIVE_FILENAME="$PACKAGE_NAME.pkg" PKG="${OBJROOT}/../BuildProductsPath/${CONFIGURATION}/${ARCHIVE_FILENAME}" if [ -f "${PKG}" ]; then mkdir "${PACKAGES}" cp -r "${PKG}" "${PACKAGES}" fi
在Xcode 5中,请将此值用于
PKG
:
PKG="${OBJROOT}/ArchiveIntermediates/${TARGET_NAME}/BuildProductsPath/${CONFIGURATION}/${ARCHIVE_FILENAME}"
如果您的版本控件未存储Xcode Scheme信息,我建议将此作为外壳程序脚本添加到您的项目中,这样您就可以通过将脚本从工作区拖到后操作中来简单地还原操作。
有两种不同类型的脚本:JavaScript in Distribution Definition Files和Shell脚本。
我在WhiteBox - PackageMaker How-to中找到的有关Shell脚本的最佳文档,但是请谨慎阅读,因为它是指旧的软件包格式。
目的地选择窗格
仅向用户提供目标选择选项-“为此计算机的所有用户安装”。该选项在视觉上显示为选中状态,但用户需要单击该选项才能继续安装,从而造成一些混乱。
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9iVU15YS5wbmcifQ==” alt =“显示安装程序错误的示例”>“>
[Apples文档建议使用<domains enable_anywhere ... />
,但这会触发新的更具错误性的Destination Select窗格,Apple不在其任何包装中使用。
使用不推荐使用的<options rootVolumeOnly="true" />
,您可以得到旧的“目标选择窗格”。
您要将项目安装到当前用户的主文件夹中。
简短回答:请勿尝试!
长答案:真的;不要尝试!读取Installer Problems and Solutions。读完这篇文章你知道我做了什么吗?我很笨,可以尝试一下。告诉自己,我确定他们已经解决了10.7或10.8中的问题。
首先,我不时看到上述“目标选择窗格错误”。那应该阻止了我,但是我忽略了它。如果您不想在发布软件后的一个星期内花时间回复支持电子邮件,则必须单击一次漂亮的蓝色选项后再单击它们。
您现在认为您的用户足够聪明,可以理解面板,不是吗?好了,这是关于主文件夹安装的另一件事,它们不起作用!
我在大约10台不同操作系统版本的机器上进行了两周的测试,但没有失败,并且从未失败。所以我发货了。在发布的一个小时内,我向无法安装它的用户表示衷心的感谢。日志提示您将无法解决的权限问题。
因此,让我们再重复一遍:我们不使用Installer进行主文件夹安装!
productbuild
不接受用于欢迎,自述,许可和结论的RTFD。
从开始的RTFD文件开始就支持安装程序,以使漂亮的欢迎屏幕带有图像,但是productbuild不接受它们。
解决方法:productbuild
完成后,使用虚拟rtf文件并将其替换为软件包中的文件。
注意:您还可以在RTFD文件中包含Retina图像。为此,请使用多图像tiff文件:tiffutil -cat Welcome.tif Welcome_2x.tif -out FinalWelcome.tif
。更多details。
使用BundlePostInstallScriptPath
脚本完成安装后启动应用程序:工具或Apple Remote Desktop完成的命令行安装时才运行它。#!/bin/bash LOGGED_IN_USER_ID=`id -u "${USER}"` if [ "${COMMAND_LINE_INSTALL}" = "" ] then /bin/launchctl asuser "${LOGGED_IN_USER_ID}" /usr/bin/open -g PATH_OR_BUNDLE_ID fi exit 0
重要的是,以登录用户身份而不是安装程序用户身份运行该应用程序。这是通过launchctl asuser uid路径
完成的。另外,我们仅在不是通过installer
StéphaneSudre有一个非常有趣的应用程序,它可以为您完成所有这些工作,可编写脚本/支持从命令行进行构建,具有非常漂亮的GUI,并且免费。可悲的是:它被称为“包裹”,因此无法在Google中找到。
我希望我在开始手工制作自己的脚本之前就已经知道这一点。
仅供参考,对于那些试图为捆绑软件或插件创建软件包安装程序的人,这很容易:
pkgbuild --component "Color Lists.colorPicker" --install-location ~/Library/ColorPickers ColorLists.pkg
A +1接受的答案:
安装程序中的目的地选择
如果希望在用户域和系统域之间选择域(也称为目标域),则不要尝试<domains enable_anywhere="true">
,请使用以下命令:
<domains enable_currentUserHome="true" enable_localSystem="true"/>
[enable_currentUserHome在~/Applications/
下安装应用程序应用程序,enable_localSystem
允许在/Application
下安装应用程序>
[我已经在El Capitan 10.11.6(15G1217)中进行了尝试,在1台开发机和2台我尝试过的不同VM上似乎运行良好。
Here is a build script从构建根目录创建签名的安装程序包。
#!/bin/bash
# TRIMCheck build script
# Copyright Doug Richardson 2015
# Usage: build.sh
#
# The result is a disk image that contains the TRIMCheck installer.
#
DSTROOT=/tmp/trimcheck.dst
SRCROOT=/tmp/trimcheck.src
INSTALLER_PATH=/tmp/trimcheck
INSTALLER_PKG="TRIMCheck.pkg"
INSTALLER="$INSTALLER_PATH/$INSTALLER_PKG"
#
# Clean out anything that doesn't belong.
#
echo Going to clean out build directories
rm -rf build $DSTROOT $SRCROOT $INSTALLER_PATH
echo Build directories cleaned out
#
# Build
#
echo ------------------
echo Installing Sources
echo ------------------
xcodebuild -project TRIMCheck.xcodeproj installsrc SRCROOT=$SRCROOT || exit 1
echo ----------------
echo Building Project
echo ----------------
pushd $SRCROOT
xcodebuild -project TRIMCheck.xcodeproj -target trimcheck -configuration Release install || exit 1
popd
echo ------------------
echo Building Installer
echo ------------------
mkdir -p "$INSTALLER_PATH" || exit 1
echo "Runing pkgbuild. Note you must be connected to Internet for this to work as it"
echo "has to contact a time server in order to generate a trusted timestamp. See"
echo "man pkgbuild for more info under SIGNED PACKAGES."
pkgbuild --identifier "com.delicioussafari.TRIMCheck" \
--sign "Developer ID Installer: Douglas Richardson (4L84QT8KA9)" \
--root "$DSTROOT" \
"$INSTALLER" || exit 1
echo Successfully built TRIMCheck
open "$INSTALLER_PATH"
exit 0
StéphaneSudre有一个非常有趣的应用程序,它可以为您完成所有这些工作,可编写脚本/支持从命令行进行构建,具有非常漂亮的GUI,并且免费。可悲的是:它被称为“包裹”,因此无法在Google中找到。
仅供参考,对于那些试图为捆绑软件或插件创建软件包安装程序的人,这很容易:
A +1接受的答案:
Here is a build script从构建根目录创建签名的安装程序包。
#!/bin/bash
# TRIMCheck build script
# Copyright Doug Richardson 2015
# Usage: build.sh
#
# The result is a disk image that contains the TRIMCheck installer.
#
DSTROOT=/tmp/trimcheck.dst
SRCROOT=/tmp/trimcheck.src
INSTALLER_PATH=/tmp/trimcheck
INSTALLER_PKG="TRIMCheck.pkg"
INSTALLER="$INSTALLER_PATH/$INSTALLER_PKG"
#
# Clean out anything that doesn't belong.
#
echo Going to clean out build directories
rm -rf build $DSTROOT $SRCROOT $INSTALLER_PATH
echo Build directories cleaned out
#
# Build
#
echo ------------------
echo Installing Sources
echo ------------------
xcodebuild -project TRIMCheck.xcodeproj installsrc SRCROOT=$SRCROOT || exit 1
echo ----------------
echo Building Project
echo ----------------
pushd $SRCROOT
xcodebuild -project TRIMCheck.xcodeproj -target trimcheck -configuration Release install || exit 1
popd
echo ------------------
echo Building Installer
echo ------------------
mkdir -p "$INSTALLER_PATH" || exit 1
echo "Runing pkgbuild. Note you must be connected to Internet for this to work as it"
echo "has to contact a time server in order to generate a trusted timestamp. See"
echo "man pkgbuild for more info under SIGNED PACKAGES."
pkgbuild --identifier "com.delicioussafari.TRIMCheck" \
--sign "Developer ID Installer: Douglas Richardson (4L84QT8KA9)" \
--root "$DSTROOT" \
"$INSTALLER" || exit 1
echo Successfully built TRIMCheck
open "$INSTALLER_PATH"
exit 0