¿Cómo creo un DMG atractivo para Mac OS X usando herramientas de línea de comandos?

Necesito crear un buen instalador para una aplicación Mac. Quiero que sea una imagen de disco (DMG), con un tamaño, diseño e imagen de fondo predefinidos.

Necesito hacer esto programáticamente en un script, para integrarlo en un sistema de comstackción existente (más que nada un sistema de paquete, ya que solo crea instaladores. Las comstackciones se hacen por separado).

Ya he hecho la creación de DMG usando “hdiutil”, lo que no he descubierto aún es cómo hacer un diseño de icono y especificar un bitmap de fondo.

Después de muchas investigaciones, se me ocurrió esta respuesta, y la expongo aquí como respuesta a mi propia pregunta, como referencia:

  1. Asegúrese de que “Habilitar el acceso para dispositivos de asistencia” esté marcado en Preferencias del sistema >> Acceso universal. Se requiere que AppleScript funcione. Es posible que deba reiniciarse después de este cambio (de lo contrario, no funciona en Mac OS X Server 10.4).

  2. Crea un R / W DMG. Debe ser más grande de lo que será el resultado. En este ejemplo, la variable de bash “tamaño” contiene el tamaño en Kb y el contenido de la carpeta en la variable de origen “bash” se copiará en el DMG:

    hdiutil create -srcfolder "${source}" -volname "${title}" -fs HFS+ \ -fsargs "-cc=64,a=16,e=16" -format UDRW -size ${size}k pack.temp.dmg 
  3. Monte la imagen del disco y almacene el nombre del dispositivo (es posible que desee utilizar el modo de suspensión durante unos segundos después de esta operación):

     device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \ egrep '^/dev/' | sed 1q | awk '{print $1}') 
  4. Guarde la imagen de fondo (en formato PNG) en una carpeta llamada “.background” en el DMG, y almacene su nombre en la variable “backgroundPictureName”.

  5. Use AppleScript para establecer los estilos visuales (el nombre de .app debe estar en la variable bash “nombre de aplicación”, use variables para las demás propiedades según sea necesario):

     echo ' tell application "Finder" tell disk "'${title}'" open set current view of container window to icon view set toolbar visible of container window to false set statusbar visible of container window to false set the bounds of container window to {400, 100, 885, 430} set theViewOptions to the icon view options of container window set arrangement of theViewOptions to not arranged set icon size of theViewOptions to 72 set background picture of theViewOptions to file ".background:'${backgroundPictureName}'" make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"} set position of item "'${applicationName}'" of container window to {100, 100} set position of item "Applications" of container window to {375, 100} update without registering applications delay 5 close end tell end tell ' | osascript 
  6. Finialice el DMG configurando permisos, comprimiéndolo y liberándolo:

     chmod -Rf go-w /Volumes/"${title}" sync sync hdiutil detach ${device} hdiutil convert "/pack.temp.dmg" -format UDZO -imagekey zlib-level=9 -o "${finalDMGName}" rm -f /pack.temp.dmg 

En Snow Leopard, el AppleScript anterior no establecerá la posición del icono correctamente, parece ser un error Snow Leopard. Una solución alternativa es simplemente llamar cerrar / abrir después de configurar los icons, es decir:

 .. set position of item "'${applicationName}'" of container window to {100, 100} set position of item "Applications" of container window to {375, 100} close open 

Hay un pequeño script de Bash llamado create-dmg que crea DMG sofisticados con fondos personalizados, posicionamiento de icono personalizado y nombre de volumen.

Lo construí hace muchos años para la compañía que dirigía en ese momento; sobrevive gracias a la contribución de otras personas desde entonces y, según los informes, funciona bien.

También hay node-appdmg que parece un esfuerzo más moderno y activo basado en Node.js; échale un vistazo también.

No vayas allí. Como desarrollador de Mac a largo plazo, puedo asegurarle que ninguna solución funciona realmente bien. Intenté muchas soluciones, pero no todas son buenas. Creo que el problema es que Apple realmente no documenta el formato de metadatos para los datos necesarios.

Así es como lo estoy haciendo durante mucho tiempo, con mucho éxito:

  1. Cree un nuevo DMG, escribible (!), Lo suficientemente grande como para contener los archivos binarios y extra esperados, como el archivo Léame (disperso podría funcionar).

  2. Montar el DMG y darle un diseño manual en Finder o con las herramientas que le convengan para hacerlo (consulte el enlace FileStorm en la parte inferior para obtener una buena herramienta). La imagen de fondo suele ser una imagen que colocamos en una carpeta oculta (“algo”) en el DMG. Ponga una copia de su aplicación allí (cualquier versión, incluso una obsoleta hará). Copie otros archivos (alias, léame, etc.) que desee allí, de nuevo, las versiones obsoletas le irán bien. Asegúrese de que los icons tengan los tamaños y posiciones correctos (IOW, diseñe el DMG de la manera que desee).

  3. Desmonte la DMG nuevamente, todas las configuraciones deberían estar almacenadas por ahora.

  4. Escriba un script crear DMG, que funciona de la siguiente manera:

    • Copia el DMG, por lo que el original nunca se vuelve a tocar.
    • Monta la copia.
    • Reemplaza todos los archivos con los más actualizados (por ejemplo, la última aplicación después de la comstackción). Simplemente puede usar mv o ídem para eso en la línea de comando. Tenga en cuenta que cuando reemplace un archivo así, el ícono permanecerá igual, la posición permanecerá igual, todo excepto el contenido del archivo (o directorio) se mantendrá igual (al menos con ídem, que generalmente usamos para esa tarea) . Por supuesto, también puede reemplazar la imagen de fondo con otra (solo asegúrese de que tenga las mismas dimensiones).
    • Después de reemplazar los archivos, haga que la secuencia de comandos desmonte la copia DMG nuevamente.
    • Finalmente, llame a hdiutil para convertir el DMG comprimible (y no modificable).

Este método puede no sonar óptimo, pero créanme, funciona muy bien en la práctica. Puedes poner el DMG original (plantilla DMG) incluso bajo control de versión (por ejemplo, SVN), por lo que si alguna vez lo cambias / destruyes accidentalmente, puedes volver a una revisión donde todavía estaba bien. Puede agregar la plantilla DMG a su proyecto Xcode, junto con todos los demás archivos que pertenecen al DMG (archivo Léame, URL, fondo), todo bajo control de versión y luego crear un objective (por ejemplo, un objective externo llamado “Crear DMG”) y allí ejecute el script DMG de arriba y agregue su antiguo objective principal como objective dependiente. Puede acceder a los archivos en el árbol de Xcode usando $ {SRCROOT} en el script (siempre es la raíz de origen de su producto) y puede acceder a los productos de comstackción usando $ {BUILT_PRODUCTS_DIR} (siempre es el directorio donde Xcode crea los resultados de comstackción) .

Resultado: en realidad, Xcode puede producir el DMG al final de la comstackción. Un DMG que está listo para lanzar. No solo puede crear un DMG de reenvío de manera bastante fácil, de hecho puede hacerlo en un proceso automatizado (en un servidor decapitado si lo desea), utilizando xcodebuild desde la línea de comando (comstackciones nocturnas automatizadas, por ejemplo).

Con respecto al diseño inicial de la plantilla, FileStorm es una buena herramienta para hacerlo. Es comercial, pero muy poderoso y fácil de usar. La versión normal cuesta menos de $ 20, por lo que es realmente asequible. Tal vez uno puede automatizar FileStorm para crear un DMG (por ejemplo, a través de AppleScript), nunca lo intentó, pero una vez que haya encontrado la plantilla perfecta DMG, es realmente fácil actualizarla para cada lanzamiento.

Actualizando esta pregunta proporcionando esta respuesta.

appdmg es un progtwig de línea de comando de código abierto simple, fácil de usar que crea archivos dmg a partir de una especificación json simple. Eche un vistazo al archivo Léame en el sitio web oficial:

https://github.com/LinusU/node-appdmg

Ejemplo rápido:

  1. Instalar appdmg

     npm install -g appdmg 
  2. Escribir un archivo json ( spec.json )

     { "title": "Test Title", "background": "background.png", "icon-size": 80, "contents": [ { "x": 192, "y": 344, "type": "file", "path": "TestApp.app" }, { "x": 448, "y": 344, "type": "link", "path": "/Applications" } ] } 
  3. Ejecute el progtwig

     appdmg spec.json test.dmg 

(descargo de responsabilidad. Soy el creador de appdmg)

Para aquellos de ustedes que están interesados ​​en este tema, debería mencionar cómo creo el DMG:

 hdiutil create XXX.dmg -volname "YYY" -fs HFS+ -srcfolder "ZZZ" 

dónde

 XXX == disk image file name (duh!) YYY == window title displayed when DMG is opened ZZZ == Path to a folder containing the files that will be copied into the DMG 

Mi aplicación, DropDMG , es una manera fácil de crear imágenes de disco con imágenes de fondo, diseños de íconos, icons de volumen personalizados y acuerdos de licencia de software. Se puede controlar desde un sistema de comstackción mediante la herramienta de línea de comandos “dropdmg” o AppleScript. Si lo desea, la imagen y la licencia de los archivos RTF se pueden almacenar en su sistema de control de versiones.

Encontré esta gran aplicación de mac para automatizar el proceso: http://www.araelium.com/dmgcanvas/ debes echar un vistazo si estás creando el instalador de dmg para tu aplicación de mac

Si desea establecer un icono de volumen personalizado, utilice el comando a continuación

 /*Add a drive icon*/ cp "/Volumes/customIcon.icns" "/Volumes/dmgName/.VolumeIcon.icns" /*SetFile -c icnC will change the creator of the file to icnC*/ SetFile -c icnC //.VolumeIcon.icns 

Ahora crea dmg de lectura / escritura

 /*to set custom icon attribute*/ SetFile -a C /Volumes/dmgName 

.DS_Store files almacena la configuración de Windows en Mac. La configuración de Windows incluye el diseño de los icons, el fondo de la ventana, el tamaño de la ventana, etc. El archivo .DS_Store es necesario para crear la ventana de las imágenes montadas para preservar la disposición de los archivos y el fondo de Windows.

Una vez que haya creado el archivo .DS_Store, puede copiarlo a su instalador creado (DMG).

También necesito usar el enfoque de línea de comando para hacer el empaquetado y la creación de dmg “programáticamente en un script”. La mejor respuesta que encontré hasta ahora es del marco de creación de versiones del Proyecto Adium (Ver R1). Existe un script personalizado (AdiumApplescriptRunner) que le permite evitar la interacción de OSX WindowsServer GUI. El enfoque “osascript applescript.scpt” requiere que inicie sesión como constructor y ejecute la creación de dmg desde una sesión de línea de comando vt100.

El sistema de administración de paquetes de OSX no es tan avanzado en comparación con otros Unixen que pueden hacer esta tarea de forma fácil y sistemática.

R1: http://hg.adium.im/adium-1.4/file/00d944a3ef16/Release

Finalmente lo conseguí trabajando en mi propio proyecto (que sucede en Xcode). Agregar estos 3 scripts a su fase de construcción creará automáticamente una imagen de disco para su producto que sea agradable y ordenada. Todo lo que tienes que hacer es construir tu proyecto y el DMG estará esperando en la carpeta de tus productos.

Script 1 (Crear imagen de disco temporal):

 #!/bin/bash #Create a R/W DMG dir="$TEMP_FILES_DIR/disk" dmg="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg" rm -rf "$dir" mkdir "$dir" cp -R "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app" "$dir" ln -s "/Applications" "$dir/Applications" mkdir "$dir/.background" cp "$PROJECT_DIR/$PROJECT_NAME/some_image.png" "$dir/.background" rm -f "$dmg" hdiutil create "$dmg" -srcfolder "$dir" -volname "$PRODUCT_NAME" -format UDRW #Mount the disk image, and store the device name hdiutil attach "$dmg" -noverify -noautoopen -readwrite 

Script 2 (Establecer script de propiedades de ventana):

 #!/usr/bin/osascript #get the dimensions of the main window using a bash script set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Main Display: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'") set x to ((width / 2) / scale) set y to ((height / 2) / scale) #get the product name using a bash script set {product_name} to words of (do shell script "printf \"%s\", $PRODUCT_NAME") set background to alias ("Volumes:"&product_name&":.background:some_image.png") tell application "Finder" tell disk product_name open set current view of container window to icon view set toolbar visible of container window to false set statusbar visible of container window to false set the bounds of container window to {x, y, (x + 479), (y + 383)} set theViewOptions to the icon view options of container window set arrangement of theViewOptions to not arranged set icon size of theViewOptions to 128 set background picture of theViewOptions to background set position of item (product_name & ".app") of container window to {100, 225} set position of item "Applications" of container window to {375, 225} update without registering applications close end tell end tell 

La medición anterior para el trabajo de ventana para mi proyecto específicamente debido al tamaño de mi imagen de fondo y resolución de icono; es posible que necesite modificar estos valores para su propio proyecto.

Script 3 (Hacer script de imagen de disco final):

 #!/bin/bash dir="$TEMP_FILES_DIR/disk" cp "$PROJECT_DIR/$PROJECT_NAME/some_other_image.png" "$dir/" #unmount the temp image file, then convert it to final image file sync sync hdiutil detach /Volumes/$PRODUCT_NAME rm -f "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg" hdiutil convert "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg" -format UDZO -imagekey zlib-level=9 -o "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg" rm -f "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg" #Change the icon of the image file sips -i "$dir/some_other_image.png" DeRez -only icns "$dir/some_other_image.png" > "$dir/tmpicns.rsrc" Rez -append "$dir/tmpicns.rsrc" -o "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg" SetFile -a C "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg" rm -rf "$dir" 

¡Asegúrate de que los archivos de imagen que estás usando estén en el directorio $ PROJECT_DIR / $ PROJECT_NAME /!

Para crear un DMG atractivo, ahora puedes usar algunas fonts abiertas bien escritas:

  • crear-dmg
  • node-appdmg
  • dmgbuild

Estas respuestas son demasiado complicadas y los tiempos han cambiado. Lo siguiente funciona bien en 10.9, los permisos son correctos y se ve bien.

Crear un DMG de solo lectura desde un directorio

 #!/bin/sh # create_dmg Frobulator Frobulator.dmg path/to/frobulator/dir [ 'Your Code Sign Identity' ] set -e VOLNAME="$1" DMG="$2" SRC_DIR="$3" CODESIGN_IDENTITY="$4" hdiutil create -srcfolder "$SRC_DIR" \ -volname "$VOLNAME" \ -fs HFS+ -fsargs "-cc=64,a=16,e=16" \ -format UDZO -imagekey zlib-level=9 "$DMG" if [ -n "$CODESIGN_IDENTITY" ]; then codesign -s "$CODESIGN_IDENTITY" -v "$DMG" fi 

Crear DMG de solo lectura con un ícono (tipo .icns)

 #!/bin/sh # create_dmg_with_icon Frobulator Frobulator.dmg path/to/frobulator/dir path/to/someicon.icns [ 'Your Code Sign Identity' ] set -e VOLNAME="$1" DMG="$2" SRC_DIR="$3" ICON_FILE="$4" CODESIGN_IDENTITY="$5" TMP_DMG="$(mktemp -u -t XXXXXXX)" trap 'RESULT=$?; rm -f "$TMP_DMG"; exit $RESULT' INT QUIT TERM EXIT hdiutil create -srcfolder "$SRC_DIR" -volname "$VOLNAME" -fs HFS+ \ -fsargs "-cc=64,a=16,e=16" -format UDRW "$TMP_DMG" TMP_DMG="${TMP_DMG}.dmg" # because OSX appends .dmg DEVICE="$(hdiutil attach -readwrite -noautoopen "$TMP_DMG" | awk 'NR==1{print$1}')" VOLUME="$(mount | grep "$DEVICE" | sed 's/^[^ ]* on //;s/ ([^)]*)$//')" # start of DMG changes cp "$ICON_FILE" "$VOLUME/.VolumeIcon.icns" SetFile -c icnC "$VOLUME/.VolumeIcon.icns" SetFile -a C "$VOLUME" # end of DMG changes hdiutil detach "$DEVICE" hdiutil convert "$TMP_DMG" -format UDZO -imagekey zlib-level=9 -o "$DMG" if [ -n "$CODESIGN_IDENTITY" ]; then codesign -s "$CODESIGN_IDENTITY" -v "$DMG" fi 

Si tiene que suceder algo más, lo más fácil es hacer una copia temporal del SRC_DIR y aplicarle cambios antes de crear un DMG.

Acabo de escribir una nueva utilidad de línea de comandos (amigable) para hacer esto. No se basa en Finder / AppleScript ni en ninguna de las API (obsoletas) de Alias ​​Manager, y es fácil de configurar y usar.

De todos modos, cualquiera que esté interesado puede encontrarlo en PyPi ; la documentación está disponible en Read The Docs .