Підготовка пакетів для встановлення macOS, які є ідентифікатором розробника


189

Примітка. Це стосується лише пакетів інсталятора OS X , пакети для подання в магазин додатків Mac відповідають іншим правилам.

Через підопічного «Mountain Lion's Gatekeeper» мені нарешті довелося взяти сценарій для складання PackageMaker за сарай і знімати його. PackageMaker вже був видалений з Xcode і переміщений у "Допоміжні інструменти для Xcode", тому, сподіваємось, він скоро буде забутий.

Питання полягає в тому, як я використовую pkgbuild, productbuildі pkgutilзамінити його?


тож я припускаю, що проблема з пакувачем - це нездатність правильно підписувати файли pkg для використання з воротарем на Mountain Lion?
JasonZ

1
Це можливо, але PackageMaker завжди був баггі пекла, і його застаріли за допомогою Mac OS X 10.6 Snow Leopard. Це заощадить ваш час у довгостроковій перспективі просто ознайомитися з новими інструментами.
каталан

@catlan: Чи є у вас офіційне посилання, яке говорить про те, що упаковка виробника застаріла 10,6?
Карл

2
@carleeto: Його ніколи не оголошували як застаріле, його просто видаляли з Xcode і врешті "зникали", як бірманський протестувальник.
помилка

5
Примітки до випуску Xcode 4.6: Deprecation of Package Maker adcdownload.apple.com/Developer_Tools/xcode_4.6/…
catlan

Відповіді:


344

Наш прикладний проект має дві цілі побудови: HelloWorld.app та Helper.app. Ми робимо пакет компонентів для кожного і об'єднуємо їх в архів продуктів .

Пакет компонентів містить корисну навантаження, яка повинна бути встановлена ​​установщиком OS X. Хоча пакет компонентів може бути встановлений самостійно, він, як правило, міститься в архіві продуктів .

Наші інструменти: PKGBUILD , productbuild і pkgutil

Після успішного "Створення та архівування" відкрийте $ BUILT_PRODUCTS_DIR в Терміналі.

$ cd ~/Library/Developer/Xcode/DerivedData/.../InstallationBuildProductsLocation
$ pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
$ pkgbuild --analyze --root ./Helper.app HelperAppComponents.plist

Це дає нам компонент-список, опис значення ви знайдете в розділі "Список властивостей компонента" . pkgbuild -root генерує пакети компонентів , якщо вам не потрібно змінювати жодні властивості за замовчуванням, ви можете опустити параметр --component-plist у наступній команді.

побудова продукту --синтезує результати у визначенні розподілу .

$ 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 ви можете змінити такі речі, як назва, фон, привітання, readme, ліцензія тощо. Ви перетворюєте пакети компонентів та визначення розповсюдження за допомогою цієї команди в архів продуктів :

$ productbuild --distribution ./Distribution.xml \
    --package-path . \
    ./Installer.pkg

Рекомендую поглянути на iTunes Installers Distribution.xml, щоб побачити, що можливо. Ви можете витягнути "Встановити iTunes.pkg" за допомогою:

$ pkgutil --expand "Install iTunes.pkg" "Install iTunes"

Давайте складемо його разом

У моєму проекті зазвичай є папка з назвою Package, яка включає такі речі, як Distribution.xml, списки компонентів, ресурси та сценарії.

Додайте етап збірки сценарію запуску під назвою "Створити пакет", який встановлено для запуску сценарію лише під час встановлення :

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та pkgutil --flattenкроків. Крім того, ви можете використовувати --sign paramenter на productbuild замість запуску productsign .

Підпишіть інсталятор OS X

Пакети підписані сертифікатом встановника ID розробника, який ви можете завантажити з утиліти для розробників .

Вони підписуючи робиться з --sign "Developer ID Installer: John Doe"параметром PKGBUILD , productbuild або productsign .

Зауважте, що якщо ви збираєтесь створити підписаний архів продуктів за допомогою збірки продуктів, немає підстав підписувати пакети компонентів .

Утиліта сертифіката розробника

Весь шлях: Скопіюйте пакет в архів Xcode

Щоб скопіювати щось у Архів Xcode, ми не можемо використовувати Фазу збірки скриптів . Для цього нам потрібно використовувати схему дій.

Відредагуйте схему та розгорніть Архів. Потім натисніть постові дії та додайте нову дію сценарію виконання :

У 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, я пропоную додати це як скрипт оболонки до свого проекту, щоб ви могли просто відновити дію, перетягнувши сценарій з робочої області в пост-дію.

Сценарій

Існує два різних сценарії: JavaScript у файлах із визначенням розподілу та скриптами оболонки.

Найкраща документація про сценарії оболонки, яку я знайшов у WhiteBox - PackageMaker How-to , але читайте це з обережністю, оскільки вона стосується старого формату пакету.

Додаткове читання

Відомі проблеми та обхідні шляхи

Виберіть область призначення

Користувачеві надається опція вибору пункту призначення лише з одним вибором - "Встановити для всіх користувачів цього комп'ютера". Параметр видається візуально вибраним, але користувачеві потрібно натиснути на нього, щоб продовжити встановлення, викликаючи певну плутанину.

Приклад показу помилки інсталятора

Документація щодо яблук рекомендує використовувати, <domains enable_anywhere ... />але це запускає нову більш помилкову панель вибору пункту призначення, яку Apple не використовує ні в одному зі своїх пакунків.

За допомогою депрекату <options rootVolumeOnly="true" />ви отримаєте стару панель вибору пункту призначення. Приклад, що показує стару панель вибору пункту призначення


Ви хочете встановити елементи в домашню папку поточного користувача.

Коротка відповідь: НЕ Спробуйте його!

Довга відповідь: дійсно; НЕ СТІЙТЕ ЇЇ! Прочитайте Проблеми та рішення інсталятора . Ви знаєте, що я зробив, навіть прочитавши це? Я був досить дурний, щоб спробувати це. Розповідаючи про себе, я впевнений, що вони виправили проблеми в 10.7 або 10.8.

Перш за все я час від часу бачив вищезгаданий помилка вибору пункту призначення. Це мало мене зупинити, але я проігнорував це. Якщо ви не хочете витрачати тиждень після того, як ви випустили програмне забезпечення, відповідаючи на електронні листи з підтримкою, що вони повинні натиснути, як тільки приємний синій вибір НЕ використовувати це.

Тепер ви думаєте, що ваші користувачі досить розумні, щоб зрозуміти панель, чи не так? Ну ось ще одна річ про встановлення домашньої папки - НЕ РОБОТИ!

Я тестував її протягом двох тижнів на приблизно 10 різних машинах з різними версіями ОС і що ні, і ніколи не виходив з ладу. Тож я його відвантажив. Протягом години після випуску я повернувся до користувачів, які просто не змогли його встановити. Журнали натякали на проблеми з дозволом, які ви не зможете виправити.

Тож повторимо це ще раз: ми не використовуємо Інсталятор для встановлення домашньої папки!


RTFD для Ласкаво просимо, Read-me, Ліцензія та Висновок не приймаються productbuild.

Інсталятор підтримує RTFD-файли з самого початку, щоб створити гарні екрани привітання із зображеннями, але збірка продуктів не приймає їх.

Обхідні шляхи: Використовуйте фіктивний rtf файл і замініть його в пакеті на після того, як productbuildбуде зроблено.

Примітка. У файлі RTFD також можуть бути зображення Retina. Використовуйте для цього файли з декількома зображеннями tiffutil -cat Welcome.tif Welcome_2x.tif -out FinalWelcome.tif. Більше деталей .


Запуск програми, коли встановлення виконується за допомогою сценарію 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

Важливо запускати додаток як зареєстрований користувач, а не як користувач, який встановлює програму. Це робиться за допомогою uid шляху запуску asuser . Крім того, ми запускаємо його лише тоді, коли це не встановлення командного рядка, виконане за допомогою інструмента інсталятора або Apple Remote Desktop .



9
Це чудовий підручник, але передбачає наявність збірних комплектів. Наприклад, якщо я мав би встановити один файл, /tmpякий слід обробити пізніше після сценарію після польоту, як я структурую список компонентів? Здається, уся наявна документація передбачає, що розробник створив її --analyzeпринаймні спочатку.
помилка

1
Якщо вам нічого не потрібно змінювати, Component Property Listбігти не потрібно --analyze. Для файлів після обробки я пропоную розмістити їх у pkg та встановити для цього місце встановлення pkg /tmp. Але, можливо, я неправильно розумію ваше запитання. Якщо це так, розмістіть його в більш детальній версії на SO.
catlan

2
Зауважте, що не має сенсу робити пакети за допомогою командного рядка, намагаючись уникнути всіх помилок у програмі для упаковки. Швидше дивіться мій коментар нижче щодо використання програми "Пакети" від Stéphane Sudre, який вирішує всі проблеми для вас!
Брам де Йонг

5
@BramdeJong "не має сенсу". Я не погоджуюсь. Apple підтримує інструменти командного рядка. Пакети - це стороннє додаток, яке не підтримується спільнотою, і може в майбутньому зламатися, якщо Apple змінить щось кардинальне. Для мене я скоріше знаю техніку командного рядка, так що, якщо Apple змінить щось різке, я можу продовжувати працювати.
Воломійк

5
$ pkgbuild --root ./HelloWorld.app помиляється (припустимо, що .app - це фактичний пакет програм). pkgbuild працює на корені призначення: тобто папці, яка ОБ'ЄДНУЄ пакет, згенерований ланцюжком інструментів xcode. Таким чином, аргументом до pkgbuild є шлях до папки, що містить пакет, який ми хочемо упакувати. Якщо не отримати цього права, ви отримаєте пакет, який містить лише папку вмісту програми. Він не встановиться як фактичний пакет програм. Подача знаходиться у складовій плісті. Якщо він не містить записи RootRelativeBundlePath із зазначенням пакету додатків, то ви вже викрутили.
Джонатан Мітчелл

185

Є одне дуже цікаве додаток від Stéphane Sudre, яке робить все це для вас, вміє писати / підтримує будівництво з командного рядка, має чудовий графічний інтерфейс і БЕЗКОШТОВНО. Сумна річ: вона називається "Пакети", що унеможливлює їх пошук в Google.

http://s.sudre.free.fr/Software/Packages/about.html

Я хотів, щоб я про це знав ще до того, як почав займатися рукоділлям власних сценаріїв.

Скріншот програми пакетів


11
Я не можу повірити, що цей пост не має більшого сенсу. Це програмне забезпечення дивовижне, і воно підтримує побудову з командного рядка.
Сезар Мендоса

1
Хтось намагався підписати пакет із цим інструментом? Я не можу отримати пункт меню "Встановити сертифікат", щоб активувати ....
GTAE86,

2
@ user283182: Дуже пізній удар, напевно, ви вже зрозуміли це, але, можливо, це допоможе іншим. Я думаю, що проблема, з якою ви стикаєтеся, детально описана в [Посібниках з огляду магазинів додатків Mac] ( developer.apple.com/app- магазин / огляд / рекомендації / mac /… ), правило 2.14: "Програми повинні бути упаковані та подані за допомогою технологій упаковки Apple, що входять до Xcode - забороняються сторонні установки
старший старший

4
Я хотів би, щоб це було платним додатком, і розробник постійно оновлює та виправляє. Packages.app є приголомшливим, особливо якщо ви хочете швидко розгорнути свій додаток. На те, щоб прочитати Огляд, створити мій проект та створити встановлений пакет, мені знадобилося 3 хвилини. Великі кудоси до Стефана.
Микола Христов

1
Цей додаток приголомшливий!
Спенсер Мюллер Дініз

3

FYI для тих, хто намагається створити інсталятор пакета для пакета чи плагіна, це просто:

pkgbuild --component "Color Lists.colorPicker" --install-location ~/Library/ColorPickers ColorLists.pkg

2
FYI, є різниця між створенням .pkg створення справжнього інсталятора з вітальним екраном, ліцензією тощо.
каталан

так, я знаю, що я ставлю це тут, тому що я не міг знайти посилання на створення інсталятора pkg для плагіна.
gngrwzrd

Це мене закатало. Просто мінімум, щоб дати заземлення.
uchuugaka

3

+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 машині розробників і двох різних віртуальних машинах, які я спробував.


Це працює добре, але з GOT'CHA: Якщо ви спочатку встановите кожного користувача, а потім встановите за машиною, установка буде в користувачеві-dir, не в машині dir, а з правами sudo. Не навпаки: ви можете встановити на машину, а потім на кожного користувача і мати її в обох місцях.
Terje Dahl

@TerjeDahl так, це тому, що після встановлення пакет переміщується до місця того ж ідентифікатора пакета, який був встановлений раніше інсталятором (і інсталятор це знає). Це може запобігти деяким налаштуванням у файлі маніфесту, які я зараз не пам’ятаю.
PnotNP

@ PnotNP Ага. Якщо ви були б настільки люб'язні, що поверталися б із тими налаштуваннями, якби ви могли згадати, то це було б чудово!
Terje Dahl

2

Ось сценарій збірки, який створює підписаний пакет інсталятора з кореня збірки.

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

1
Так, pkgbuild створює інсталятор .pkg.
Дуг Річардсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.