Как создать красивый DMG для Mac OS X с помощью инструментов командной строки?

Мне нужно создать хороший установщик для приложения Mac. Я хочу, чтобы это был образ диска (DMG) с предопределенным размером, макетом и фоновым изображением.

Мне нужно сделать это программно в сценарии, чтобы интегрировать его в существующую систему сборки (на самом деле это больше пакетная система, поскольку она создает только установщики. Сборки выполняются отдельно).

У меня уже есть создание DMG с использованием "hdiutil", но я пока не выяснил, как сделать макет пиктограммы и указать фоновое растровое изображение.

15 ответов

Решение

После долгих исследований я придумала этот ответ и тем самым выложила его здесь в качестве ответа на свой вопрос, для справки:

  1. Убедитесь, что "Включить доступ для вспомогательных устройств" отмечен в Системных настройках >> Универсальный доступ. Это необходимо для работы AppleScript. Возможно, вам придется перезагрузиться после этого изменения (иначе это не работает на Mac OS X Server 10.4).

  2. Создать R/W DMG. Он должен быть больше, чем результат. В этом примере переменная bash "size" содержит размер в килобайтах, а содержимое папки в переменной bash "source" будет скопировано в DMG:

    hdiutil create -srcfolder "${source}" -volname "${title}" -fs HFS+ \
          -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${size}k pack.temp.dmg
    
  3. Смонтируйте образ диска и сохраните имя устройства (вы можете использовать спящий режим в течение нескольких секунд после этой операции):

    device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \
             egrep '^/dev/' | sed 1q | awk '{print $1}')
    
  4. Сохраните фоновое изображение (в формате PNG) в папке с именем ".background" в DMG и сохраните его имя в переменной "backgroundPictureName".

  5. Используйте AppleScript для установки визуальных стилей (имя.app должно быть в переменной bash "applicationName", при необходимости используйте переменные для других свойств):

    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. Завершите DMG, правильно установив разрешения, сжимая и освобождая его:

    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 
    

На Snow Leopard вышеприведенный яблочный скрипт не будет правильно устанавливать положение иконки - похоже, это ошибка Snow Leopard. Один из способов - просто закрыть / открыть после установки значков, а именно:

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

Есть небольшой скрипт на Bash с именем create-dmg, который создает модные DMG с пользовательским фоном, пользовательским расположением значков и именем тома.

Я построил его много лет назад для компании, которой я руководил в то время; с тех пор он выживает благодаря чужому вкладу и, как сообщается, работает хорошо.

Также есть node-appdmg, который выглядит как более современный и активный, основанный на Node.js; проверьте это также.

Не ходи туда. Как долгосрочный разработчик Mac, я могу заверить вас, ни одно решение не работает на самом деле хорошо. Я пробовал так много решений, но все они не слишком хороши. Я думаю, что проблема в том, что Apple на самом деле не документирует формат метаданных для необходимых данных.

Вот как я это делаю долго, очень успешно:

  1. Создайте новый DMG, доступный для записи (!), Достаточно большой для размещения ожидаемых двоичных файлов и дополнительных файлов, таких как readme (sparse может работать).

  2. Смонтируйте DMG и настройте его вручную в Finder или с помощью любых инструментов, которые вам подходят для этого (см. Ссылку FileStorm внизу для хорошего инструмента). Фоновое изображение обычно представляет собой изображение, которое мы помещаем в скрытую папку (".something") на DMG. Поместите туда копию своего приложения (подойдет любая версия, даже устаревшая). Скопируйте другие файлы (псевдонимы, readme и т. Д.), Которые вам нужны, опять же, устаревшие версии будут работать нормально. Убедитесь, что значки имеют правильные размеры и позиции (IOW, расположите DMG так, как вы хотите).

  3. Снова размонтируйте DMG, все настройки должны быть сохранены.

  4. Напишите сценарий создания DMG, который работает следующим образом:

    • Он копирует DMG, поэтому оригинал никогда не трогается снова.
    • Это монтирует копию.
    • Он заменяет все файлы самыми последними (например, последним приложением после сборки). Вы можете просто использовать mv или ditto для этого в командной строке. Обратите внимание, что когда вы заменяете такой файл, значок останется прежним, позиция останется прежней, все, кроме содержимого файла (или каталога), останется прежним (по крайней мере, с тем же, что мы обычно используем для этой задачи), Конечно, вы также можете заменить фоновое изображение другим (просто убедитесь, что оно имеет те же размеры).
    • После замены файлов заставьте скрипт снова размонтировать копию DMG.
    • Наконец, вызовите hdiutil для преобразования записываемого в сжатый (и такой не записываемый) DMG.

Этот метод может показаться неоптимальным, но поверьте мне, на практике он работает очень хорошо. Вы можете поместить оригинальный DMG (шаблон DMG) даже под контроль версий (например, SVN), поэтому, если вы когда-нибудь случайно его измените / уничтожите, вы можете просто вернуться к ревизии, где все было в порядке. Вы можете добавить шаблон DMG в свой проект XCode вместе со всеми другими файлами, которые принадлежат DMG (readme, файл URL, фоновое изображение), все под контролем версий, а затем создать цель (например, внешнюю цель с именем "Create DMG") и там запустить сценарий DMG выше и добавить вашу старую основную цель в качестве зависимой цели. Вы можете получить доступ к файлам в дереве XCode, используя ${SRCROOT} в скрипте (всегда является исходным корнем вашего продукта), и вы можете получить доступ к продуктам сборки, используя ${BUILT_PRODUCTS_DIR} (это всегда каталог, где XCode создает результаты сборки),

Результат: На самом деле Xcode может создать DMG в конце сборки. DMG, который готов к выпуску. Таким образом, вы можете не только легко создать релевантный DMG, но и сделать это в автоматическом процессе (если хотите, на автономном сервере), используя xcodebuild из командной строки (например, автоматические ночные сборки).

Что касается начального макета шаблона, FileStorm является хорошим инструментом для этого. Это коммерческий, но очень мощный и простой в использовании. Обычная версия стоит менее 20 долларов, поэтому она действительно доступна. Может быть, можно автоматизировать FileStorm для создания DMG (например, через AppleScript), никогда не пробуя этого, но как только вы нашли идеальный шаблон DMG, его действительно легко обновить для каждого выпуска.

Привести этот вопрос в актуальное состояние, предоставив этот ответ.

appdmg это простая, простая в использовании программа с командной строкой с открытым исходным кодом, которая создает dmg-файлы из простой спецификации json. Посмотрите на readme на официальном сайте:

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

Быстрый пример:

  1. Установить приложение

    npm install -g appdmg
    
  2. Напишите файл 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. Запустить программу

    appdmg spec.json test.dmg
    

(отказ от ответственности. Я создатель appdmg)

Для тех из вас, кто интересуется этой темой, я должен упомянуть, как я создаю DMG:

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

где

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

Мое приложение DropDMG- это простой способ создания образов дисков с фоновыми изображениями, макетами значков, пользовательскими значками томов и лицензионными соглашениями на программное обеспечение. Им можно управлять из системы сборки с помощью инструмента командной строки dropdmg или AppleScript. При желании изображения и лицензионные RTF-файлы могут быть сохранены в вашей системе контроля версий.

Для создания красивого DMG теперь вы можете использовать несколько хорошо написанных открытых источников:

Я нашел это отличное приложение для Mac, чтобы автоматизировать процесс - http://www.araelium.com/dmgcanvas/ вы должны посмотреть, создаете ли вы dmg installer для вашего приложения Mac

Если вы хотите установить пользовательский значок громкости, используйте команду ниже

/*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 /<your path>/.VolumeIcon.icns

Теперь создайте чтение / запись DMG

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

Я наконец получил это, работая в моем собственном проекте (который, случается, в Xcode). Добавление этих 3-х сценариев к вашей фазе сборки автоматически создаст образ диска для вашего продукта, который будет красивым и аккуратным. Все, что вам нужно сделать, это построить свой проект, и DMG будет ждать в папке с вашими продуктами.

Скрипт 1 (Создать образ временного диска):

#!/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

Скрипт 2 (Установить скрипт окна свойств):

#!/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

Вышеуказанные измерения для окна работают для моего проекта, в частности, из-за размера моего фонового рисунка и разрешения значков; вам может понадобиться изменить эти значения для вашего собственного проекта.

Скрипт 3 (сделать финальный скрипт образа диска):

#!/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"

Убедитесь, что файлы изображений, которые вы используете, находятся в каталоге $PROJECT_DIR/$PROJECT_NAME/!

Файлы.DS_Store хранят настройки Windows в Mac. Настройки Windows включают в себя расположение значков, фон окна, размер окна и т. Д. Файл.DS_Store необходим для создания окна для смонтированных изображений, чтобы сохранить расположение файлов и фон окна.

После создания файла.DS_Store вы можете просто скопировать его в созданный вами установщик (DMG).

Я только что написал новую (дружественную) утилиту командной строки, чтобы сделать это. Он не зависит от Finder / AppleScript или какого-либо (устаревшего) API-интерфейса Alias ​​Manager, и его легко настраивать и использовать.

В любом случае, любой, кто заинтересован, может найти его на PyPi; документация доступна в разделе " Чтение документов".

Я использовал dmgbuild.

  • Монтаж: pip3 install dmgbuild
  • Установите свой том
  • Создайте файл настроек:
      {
    "title": "NAME",
    "background": "YOUR_BACKGROUND.png",
    "format": "UDZO",
    "compression-level": 9,
    "window": { "position": { "x": 100, "y": 100 },
                "size": { "width": 640, "height": 300 } },
    "contents": [
        { "x": 140, "y": 165, "type": "file", "path": "/Volumes/YOUR_VOLUME_NAME/YOUR_APP.app" },
        { "x": 480, "y": 165, "type": "link", "path": "/Applications" }
    ]
}
  • Значение ширины - это ширина фона.

  • Значение высоты должно быть равным высоте фона +20 для оконной панели.

  • В терминале: dmgbuild -s settings.json "YOUR_VOLUME_NAME" output.dmg

Мне также нужно использовать подход командной строки, чтобы сделать упаковку и создание dmg "программно в сценарии". Наилучший ответ, который я нашел на данный момент, - это проект сборки релизов Adium (см. R1). Существует специальный скрипт (AdiumApplescriptRunner), позволяющий избежать взаимодействия с OSX WindowsServer GUI. Подход "osascript applecript.scpt" требует, чтобы вы вошли в систему как строитель и запустили создание dmg из сеанса командной строки vt100.

Система управления пакетами OSX не настолько продвинута по сравнению с другими Unixen, которые могут выполнять эту задачу легко и систематически.

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

Эти ответы слишком сложны, и времена изменились. Следующее работает на 10.9 просто отлично, разрешения правильные и выглядит красиво.

Создать доступный только для чтения DMG из каталога

#!/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 "-c c=64,a=16,e=16" \
  -format UDZO -imagekey zlib-level=9 "$DMG"

if [ -n "$CODESIGN_IDENTITY" ]; then
  codesign -s "$CODESIGN_IDENTITY" -v "$DMG"
fi

Создать DMG только для чтения со значком (тип.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 "-c c=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

Если что-то еще должно произойти, проще всего сделать временную копию SRC_DIR и применить к ней изменения перед созданием DMG.

Другие вопросы по тегам