for - xcode descargar
Hacer paquetes de instalador de OS X como un paquete de ID Pro-Xcode Developer listo (5)
Nota: Esto es solo para paquetes de instalador OS X. Los paquetes para enviar a Mac App Store siguen reglas diferentes.
Debido a Mountain Lion''s Gatekeeper , finalmente tuve que tomar mi script de construcción PackageMaker detrás del establo y dispararlo. PackageMaker ya se eliminó de Xcode y se movió a "Auxiliary Tools for Xcode", por lo que esperamos que pronto se olvide.
La pregunta es ¿cómo uso pkgbuild
, productbuild
y pkgutil
para reemplazarlo?
A +1 a la respuesta aceptada:
Selección de destino en el instalador
Si se desea la selección del dominio (también conocido como destino) entre el dominio del usuario y el dominio del sistema, en lugar de intentar <domains enable_anywhere="true">
use lo siguiente:
<domains enable_currentUserHome="true" enable_localSystem="true"/>
enable_currentUserHome
instala la aplicación de la aplicación en ~/Applications/
y enable_localSystem
permite que la aplicación se instale en /Application
Lo intenté en El Capitán 10.11.6 (15G1217) y parece funcionar perfectamente bien en 1 máquina de revelado y en 2 máquinas virtuales diferentes que probé.
Hay una aplicación muy interesante de Stéphane Sudre que hace todo esto por ti, es guionizable / admite la construcción desde la línea de comandos, tiene una GUI super agradable y es GRATUITA. Lo triste es que se llama "Paquetes", lo que hace que sea imposible encontrarlo en google.
http://s.sudre.free.fr/Software/Packages/about.html
Ojalá lo hubiera sabido antes de empezar a elaborar a mano mis propios guiones.
Nuestro proyecto de ejemplo tiene dos objetivos de compilación: HelloWorld.app y Helper.app. Hacemos un paquete de componentes para cada uno y los combinamos en un archivo de producto .
Un paquete de componentes contiene la carga útil que instalará OS X Installer. Aunque un paquete de componentes se puede instalar solo, normalmente se incorpora a un archivo de producto .
Nuestras herramientas: pkgbuild , productbuild y pkgutil
Después de una exitosa "compilación y archivo" abra $ BUILT_PRODUCTS_DIR en la Terminal.
$ cd ~/Library/Developer/Xcode/DerivedData/.../InstallationBuildProductsLocation
$ pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
$ pkgbuild --analyze --root ./Helper.app HelperAppComponents.plist
Esto nos da el componente-plist, usted encuentra la descripción del valor en la sección pkgbuild . pkgbuild -root genera los paquetes de componentes ; si no necesita cambiar ninguna de las propiedades predeterminadas, puede omitir el parámetro --component-plist en el siguiente comando.
productbuild --synthesize resultados en una definición de distribución .
$ 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
En Distribution.xml puede cambiar cosas como título, fondo, bienvenida, archivo Léame, licencia, etc. Convierta los paquetes de componentes y la definición de distribución con este comando en un archivo de producto :
$ productbuild --distribution ./Distribution.xml /
--package-path . /
./Installer.pkg
Recomiendo echar un vistazo a iTunes Installers Distribution.xml para ver qué es posible. Puede extraer "Instalar iTunes.pkg" con:
$ pkgutil --expand "Install iTunes.pkg" "Install iTunes"
Vamos a armarlo
Normalmente tengo una carpeta llamada Paquete en mi proyecto que incluye cosas como Distribution.xml, component-plists, recursos y scripts.
Agregue una fase de compilación de ejecución de ejecución denominada "Generar paquete", que se establece en Ejecutar script solo cuando se instala :
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}"
Si no tiene que cambiar el paquete después de generarlo con productbuild , puede deshacerse de los pkgutil --expand
y pkgutil --flatten
. También podría usar el parámetro --sign en productbuild en lugar de ejecutar la etiqueta de producto .
Firme un instalador OS X
Los paquetes se firman con el certificado de instalador de ID de desarrollador que puede descargar de Developer Certificate Utility .
La firma se realiza con el --sign "Developer ID Installer: John Doe"
de pkgbuild , productbuild o productsign .
Tenga en cuenta que si va a crear un archivo de producto firmado utilizando productbuild, no hay ninguna razón para firmar los paquetes de componentes .
Todo el camino: Copie el paquete en el archivo de Xcode
Para copiar algo en el archivo de Xcode, no podemos usar la fase de compilación Ejecutar script . Para esto, necesitamos usar una Acción del Esquema.
Editar esquema y expandir Archivo. A continuación, haga clic en acciones posteriores y agregue una nueva acción ejecutar script :
En 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
En Xcode 5, use este valor para PKG
:
PKG="${OBJROOT}/ArchiveIntermediates/${TARGET_NAME}/BuildProductsPath/${CONFIGURATION}/${ARCHIVE_FILENAME}"
En caso de que su control de versión no almacene la información del Esquema Xcode, le sugiero que agregue esto como un guión de shell a su proyecto para que pueda restaurar la acción simplemente arrastrando el guión desde el área de trabajo a la acción posterior.
Scripting
Hay dos tipos diferentes de secuencias de comandos: JavaScript en archivos de definición de distribución y scripts de shell.
La mejor documentación sobre los scripts de Shell que encontré en WhiteBox - PackageMaker How-to , pero lea esto con precaución porque se refiere al formato del paquete anterior.
Lectura adicional
- Formato de paquete plano: la documentación faltante
- Problemas y soluciones del instalador
- Trucos estúpidos con pkgbuild
Problemas conocidos y soluciones
Panel de selección de destino
Al usuario se le presenta la opción de selección de destino con solo una opción: "Instalar para todos los usuarios de esta computadora". La opción aparece seleccionada visualmente, pero el usuario debe hacer clic en ella para continuar con la instalación, lo que causa cierta confusión.
Apples Documentation recomienda utilizar <domains enable_anywhere ... />
pero esto desencadena el nuevo Panel de Selección de Destino con más errores que Apple no usa en ninguno de sus Paquetes.
Al usar las <options rootVolumeOnly="true" />
desaprobación <options rootVolumeOnly="true" />
obtendrá el antiguo panel de selección de destino.
Desea instalar elementos en la carpeta de inicio del usuario actual.
Respuesta corta: ¡NO INTENTE!
Respuesta larga: REALMENTE; ¡NO LO INTENTES! Lea los problemas y soluciones del instalador . ¿Sabes lo que hice incluso después de leer esto? Fui lo suficientemente estúpido como para intentarlo. Diciéndome a mí mismo, estoy seguro de que arreglaron los problemas en 10.7 o 10.8.
En primer lugar, vi de vez en cuando el error de panel de destino seleccionado anteriormente. Eso debería haberme detenido, pero lo ignoré. Si no quiere pasar la semana después de haber lanzado su software para contestar los correos electrónicos de soporte que deben hacer clic una vez, la buena selección azul NO lo use.
Ahora está pensando que sus usuarios son lo suficientemente inteligentes como para figurar el panel, ¿verdad? Bueno, aquí hay otra cosa sobre la instalación de carpetas de inicio, ¡NO FUNCIONAN!
Lo probé durante dos semanas en alrededor de 10 máquinas diferentes con diferentes versiones de sistema operativo y lo que no, y nunca falló. Entonces lo envié. Una hora después de la publicación, recuerdo a los usuarios que simplemente no podían instalarlo. Los registros aludían a problemas de permisos que no podrás solucionar.
Así que vamos a repetirlo una vez más: ¡no usamos el instalador para la instalación de carpetas de inicio!
RTFD para Welcome, Read-me, License y Conclusion no es aceptado por productbuild
.
El instalador admitió desde el principio los archivos RTFD para hacer bonitas pantallas de bienvenida con imágenes, pero productbuild no las acepta.
Soluciones temporales: utilice un archivo ficticio rtf y reemplácelo en el paquete antes de que se productbuild
.
Nota: También puede tener imágenes Retina dentro del archivo RTFD. Utilice archivos tiff de varias imágenes para esto: tiffutil -cat Welcome.tif Welcome_2x.tif -out FinalWelcome.tif
. Más details
Iniciar una aplicación cuando la instalación se realiza con un script BundlePostInstallScriptPath :
#!/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 importante ejecutar la aplicación como usuario conectado, no como usuario del instalador. Esto se hace con la ruta launchctl asuser uid . Además, solo lo ejecutamos cuando no se trata de una instalación de línea de comandos, realizada con la herramienta de instalación o Apple Remote Desktop .
Para su información para aquellos que están tratando de crear un instalador de paquetes para un paquete o complemento, es fácil:
pkgbuild --component "Color Lists.colorPicker" --install-location ~/Library/ColorPickers ColorLists.pkg
Aquí hay un script de compilación que crea un paquete de instalador firmado a partir de una raíz de compilación.
#!/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