Hinweis: Dies gilt nur für OS X Installer Pakete, für Pakete, die im Mac App Store eingereicht werden, gelten andere Regeln.
Wegen Mountain Lion's Gatekeeper musste ich schließlich mein PackageMaker Build-Skript hinter die Scheune bringen und es erschießen. PackageMaker wurde bereits aus Xcode entfernt und in "Auxiliary Tools for Xcode" verschoben, so dass es hoffentlich bald vergessen sein wird.
Die Frage ist, wie kann ich pkgbuild
, productbuild
und pkgutil
verwenden, um es zu ersetzen?
Nach einem erfolgreichen "Build and Archive" öffnen Sie $BUILT_PRODUCTS_DIR im Terminal.
$ cd ~/Library/Developer/Xcode/DerivedData/.../InstallationBuildProductsLocation
$ pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
$ pkgbuild --analyze --root ./Helper.app HelperAppComponents.plist
Dies gibt uns die Komponentenliste, die Beschreibung der Werte finden Sie im Abschnitt "Component Property List". pkgbuild -root erzeugt die Komponentenpakete, wenn Sie keine der Standardeigenschaften ändern müssen, können Sie den Parameter --component-plist im folgenden Befehl weglassen. productbuild --synthesize ergibt eine 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
In der Distribution.xml können Sie Dinge wie Titel, Hintergrund, Willkommen, Readme, Lizenz und so weiter ändern. Sie verwandeln Ihre Komponentenpakete und Ihre Distributionsdefinition mit diesem Befehl in ein Produktarchiv:
$ productbuild --distribution ./Distribution.xml \
--package-path . \
./Installer.pkg
Ich empfehle, einen Blick auf iTunes Installers Distribution.xml zu werfen, um zu sehen, was möglich ist. Sie können "Install iTunes.pkg" extrahieren mit:
$ pkgutil --expand "Install iTunes.pkg" "Install iTunes"
Ich habe normalerweise einen Ordner namens Package in meinem Projekt, der Dinge wie Distribution.xml, Komponentenlisten, Ressourcen und Skripte enthält. Fügen Sie eine Run Script Build Phase namens "Generate Package" hinzu, die auf Run script only when installing gesetzt ist:
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}"
pkgutil --expand
und pkgutil --flatten
weglassen. Sie könnten auch den --sign-Parameter bei productbuild verwenden, anstatt productsign auszuführen.
Ein OS X-Installationsprogramm signieren--sign "Developer ID Installer: John Doe"
Parameter von pkgbuild, productbuild oder productsign.
Beachten Sie, dass es keinen Grund gibt, die Komponentenpakete zu signieren, wenn Sie ein signiertes Produktarchiv mit productbuild erstellen.
Dienstprogramm für Entwicklerzertifikate
So geht's: Paket in Xcode-Archiv kopierenUm etwas in das Xcode Archiv zu kopieren, können wir nicht die Run Script Build Phase verwenden. Hierfür müssen wir eine Scheme Action verwenden. Bearbeiten Sie Scheme und erweitern Sie Archive. Klicken Sie dann auf Post-Aktionen und fügen Sie eine New Run Script Action hinzu: In 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
Verwenden Sie in Xcode 5 stattdessen diesen Wert für PKG
:
PKG="${OBJROOT}/ArchiveIntermediates/${TARGET_NAME}/BuildProductsPath/${CONFIGURATION}/${ARCHIVE_FILENAME}"
<domains enable_anywhere ... />
, aber das löst das neue, fehlerhaftere Zielauswahlfenster aus, das Apple in keinem seiner Pakete verwendet.
Wenn Sie die veraltete Option <options rootVolumeOnly="true" />
verwenden, erhalten Sie das alte Zielauswahlfenster.
productbuild
nicht akzeptiert.
Installer unterstützte von Anfang an RTFD-Dateien, um hübsche Willkommensbildschirme mit Bildern zu erstellen, aber productbuild akzeptiert sie nicht.
Umgehungen:
Verwenden Sie eine Dummy-RTF-Datei und ersetzen Sie diese im Paket, nachdem productbuild
fertig ist.
Hinweis: Sie können auch Retina-Bilder innerhalb der RTFD-Datei verwenden. Verwenden Sie dazu tiff-Dateien mit mehreren Bildern: tiffutil -cat Welcome.tif Welcome_2x.tif -out FinalWelcome.tif
. Mehr Details.Starten einer Anwendung, wenn die Installation mit einem BundlePostInstallScriptPath-Skript abgeschlossen ist:
#!/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
Es gibt eine sehr interessante Anwendung von Stéphane Sudre, die all dies für Sie tut, ist skriptfähig / unterstützt die Erstellung von der Kommandozeile, hat eine super nette GUI und ist GRATIS. Traurige Sache ist: es heißt "Packages", was es unmöglich macht, in Google zu finden.
http://s.sudre.free.fr/Software/Packages/about.html
Ich wünschte, ich hätte davon gewusst, bevor ich angefangen habe, meine eigenen Skripte zu basteln.
Hier ist ein Build-Skript, das ein signiertes Installationspaket aus einem Build-Root erstellt.
#!/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