Membuat Paket Pemasang macOS yang siap dengan ID Pengembang

189

Catatan: Ini hanya untuk paket Pemasang OS X , paket untuk pengiriman ke Mac App Store mengikuti aturan yang berbeda.

Karena Gatekeeper Mountain Lion, saya akhirnya harus mengambil skrip pembuat PackageMaker saya di belakang gudang dan menembaknya. PackageMaker sudah dihapus dari Xcode dan dipindahkan ke "Alat Bantu untuk Xcode", jadi mudah-mudahan itu akan segera dilupakan.

Pertanyaannya adalah bagaimana cara menggunakan pkgbuild, productbuilddan pkgutilmenggantinya?

Catlan
sumber
jadi saya menganggap masalah dengan pembuat paket adalah ketidakmampuan untuk benar menandatangani file pkg untuk digunakan dengan gatekeeper di Mountain Lion?
JasonZ
1
Itu mungkin, tetapi PackageMaker selalu buggy, dan sudah usang dengan Mac OS X 10.6 Snow Leopard. Ini akan menghemat waktu Anda dalam jangka panjang untuk membiasakan diri dengan alat baru.
catlan
@catlan: Apakah Anda memiliki tautan resmi yang mengatakan pembuat paket telah dihentikan pada 10.6?
Carl
2
@carleeto: Tidak pernah diumumkan sebagai usang, baru saja dihapus dari Xcode dan akhirnya "menghilang" seperti seorang demonstran Burma.
bug
5
Catatan rilis Xcode 4.6: Penghentian Package Maker adcdownload.apple.com/Developer_Tools/xcode_4.6/…
catlan

Jawaban:

344

Proyek contoh kami memiliki dua target pembangunan: HelloWorld.app dan Helper.app. Kami membuat paket komponen untuk masing-masing dan menggabungkannya ke dalam arsip produk .

Sebuah paket komponen berisi muatan yang akan diinstal oleh X Installer OS. Meskipun paket komponen dapat diinstal sendiri, paket itu biasanya dimasukkan ke dalam arsip produk .

Alat kami: pkgbuild , productbuild , dan pkgutil

Setelah "Build and Archive" berhasil, buka $ BUILT_PRODUCTS_DIR di Terminal.

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

Ini memberi kita komponen-plist, Anda menemukan deskripsi nilai di bagian "Daftar Properti Komponen" . pkgbuild -root menghasilkan paket komponen , jika Anda tidak perlu mengubah properti default apa pun, Anda dapat menghilangkan parameter --component-plist pada perintah berikut.

productbuild - hasil sintesis dalam Definisi Distribusi .

$ 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 

Di Distribution.xml Anda dapat mengubah hal-hal seperti judul, latar belakang, selamat datang, readme, lisensi, dan sebagainya. Anda mengubah paket komponen dan definisi distribusi Anda dengan perintah ini menjadi arsip produk :

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

Saya sarankan untuk melihatnya iTunes Installers Distribution.xml untuk melihat apa yang mungkin. Anda dapat mengekstrak "Instal iTunes.pkg" dengan:

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

Mari kita kumpulkan

Saya biasanya memiliki folder bernama Paket dalam proyek saya yang mencakup hal-hal seperti Distribution.xml, komponen-plists, sumber daya dan skrip.

Tambahkan Fase Pembuatan Skrip Run yang dinamai "Generate Package", yang disetel ke skrip Run hanya saat menginstal :

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}"

Jika Anda tidak perlu mengubah paket setelah dibuat dengan productbuild, Anda dapat menyingkirkan pkgutil --expanddan pkgutil --flattenlangkah - langkahnya. Juga Anda bisa menggunakan --sign paramenter pada productbuild bukan berjalan productsign .

Tanda tangani Pemasang OS X

Paket ditandatangani dengan sertifikat Pemasang ID Pengembang yang dapat Anda unduh dari Utilitas Sertifikat Pengembang .

Penandatanganan mereka dilakukan dengan --sign "Developer ID Installer: John Doe"parameter pkgbuild , productbuild atau productsign .

Perhatikan bahwa jika Anda akan membuat arsip produk yang ditandatangani menggunakan productbuild, tidak ada alasan untuk menandatangani paket komponen .

Utilitas Sertifikat Pengembang

Semua jalan: Salin Paket ke Arsip Xcode

Untuk menyalin sesuatu ke Arsip Xcode kita tidak bisa menggunakan Fase Pembuatan Skrip Jalankan . Untuk ini, kita perlu menggunakan Skema Aksi.

Edit Skema dan perluas Arsip. Kemudian klik post-action dan tambahkan New Run Script Action :

Dalam 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

Di Xcode 5, gunakan nilai ini sebagai PKGgantinya:

PKG="${OBJROOT}/ArchiveIntermediates/${TARGET_NAME}/BuildProductsPath/${CONFIGURATION}/${ARCHIVE_FILENAME}"

Jika kontrol versi Anda tidak menyimpan informasi Skema Xcode, saya sarankan untuk menambahkan ini sebagai skrip shell ke proyek Anda sehingga Anda dapat dengan mudah mengembalikan tindakan dengan menyeret skrip dari ruang kerja ke dalam post-action.

Scripting

Ada dua jenis skrip: JavaScript di File Definisi Distribusi dan Skrip Shell.

Dokumentasi terbaik tentang Shell Script yang saya temukan di WhiteBox - PackageMaker How-to , tetapi baca ini dengan hati-hati karena mengacu pada format paket lama.

Bacaan Tambahan

Masalah dan Penanganan Masalah yang Diketahui

Panel Pilih Tujuan

Pengguna disajikan dengan opsi pilih tujuan dengan hanya satu pilihan - "Instal untuk semua pengguna komputer ini". Opsi muncul secara visual dipilih, tetapi pengguna perlu mengkliknya untuk melanjutkan dengan instalasi, menyebabkan beberapa kebingungan.

Contoh menunjukkan bug penginstal

Dokumentasi Apel merekomendasikan untuk digunakan <domains enable_anywhere ... />tetapi ini memicu Pane Select Destination yang lebih buggy baru yang tidak digunakan Apple dalam Paket mereka.

Menggunakan deprecate <options rootVolumeOnly="true" />memberi Anda Pane Pilih Tujuan lama. Contoh menunjukkan Pane Pilih Tujuan lama


Anda ingin menginstal item ke folder home pengguna saat ini.

Jawaban singkat: JANGAN MENCOBANYA!

Jawaban panjang: BENAR-BENAR; JANGAN MENCOBANYA! Baca Masalah dan Solusi Pemasang . Anda tahu apa yang saya lakukan bahkan setelah membaca ini? Saya cukup bodoh untuk mencobanya. Mengatakan pada diri sendiri, saya yakin mereka memperbaiki masalah di 10.7 atau 10.8.

Pertama-tama saya melihat dari waktu ke waktu, Destinasi Pilih Pane Bug yang disebutkan di atas. Itu seharusnya menghentikan saya, tetapi saya mengabaikannya. Jika Anda tidak ingin menghabiskan waktu seminggu setelah Anda merilis perangkat lunak Anda menjawab e-mail dukungan bahwa mereka harus mengklik sekali pilihan biru yang bagus JANGAN gunakan ini.

Anda sekarang berpikir bahwa pengguna Anda cukup pintar untuk mengetahui panelnya, bukan? Nah di sini ada satu hal lagi tentang pemasangan folder rumah, MEREKA TIDAK BEKERJA!

Saya mengujinya selama dua minggu pada sekitar 10 mesin yang berbeda dengan versi OS yang berbeda dan apa yang tidak, dan tidak pernah gagal. Jadi saya mengirimnya. Dalam satu jam dari rilis saya balas mengenang dari pengguna yang tidak bisa menginstalnya. Log mengisyaratkan masalah izin Anda tidak akan dapat memperbaikinya.

Jadi mari kita ulangi sekali lagi: Kami tidak menggunakan Installer untuk instalasi folder rumah!


RTFD untuk Selamat Datang, Baca-saya, Lisensi dan Kesimpulan tidak diterima oleh productbuild.

Pemasang didukung sejak awal file RTFD untuk membuat layar Selamat Datang cantik dengan gambar, tetapi productbuild tidak menerimanya.

Penanganan masalah: Gunakan file dummy rtf dan ganti dalam paket dengan setelah productbuildselesai.

Catatan: Anda juga dapat memiliki gambar Retina di dalam file RTFD. Menggunakan multi-file gambar tiff untuk ini: tiffutil -cat Welcome.tif Welcome_2x.tif -out FinalWelcome.tif. Lebih detail .


Memulai aplikasi saat instalasi dilakukan dengan skrip 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

Penting untuk menjalankan aplikasi sebagai pengguna yang masuk, bukan sebagai pengguna pemasang. Ini dilakukan dengan launchctl asuser uid path . Kami juga hanya menjalankannya saat itu bukan instalasi baris perintah, dilakukan dengan alat penginstal atau Apple Remote Desktop .


catlan
sumber
9
Ini adalah tutorial yang sangat baik, tetapi mengasumsikan keberadaan bundel prefabrikasi. Jika saya, misalnya, menginstal satu file ke /tmpuntuk diproses nanti dalam skrip postflight, bagaimana cara menyusun daftar komponen? Semua dokumentasi yang tersedia tampaknya menganggap bahwa pengembang telah membuatnya --analyze, setidaknya pada awalnya.
bug
1
Jika Anda tidak perlu mengubah apa pun di dalam, Component Property ListAnda tidak perlu lari --analyze. Untuk file postprocessing saya sarankan memasukkan semuanya ke dalam pkg dan mengatur lokasi pemasangan pkg ke /tmp. Tapi mungkin saya salah paham pertanyaan Anda. Jika demikian poskan dalam versi yang lebih detail pada SO.
catlan
2
Harap perhatikan bahwa sama sekali tidak masuk akal untuk membuat paket melalui baris perintah, mencoba untuk menghindari semua bug di aplikasi pengemasan. Alih-alih lihat komentar saya di bawah ini tentang menggunakan aplikasi "Paket" oleh Stéphane Sudre yang menyelesaikan semua masalah untuk Anda!
Bram de Jong
5
@BramdeJong "tidak masuk akal". Saya tidak setuju. Apple memelihara alat-alat baris perintah. Paket adalah aplikasi pihak ketiga yang tidak didukung komunitas dan dapat rusak di masa depan jika Apple mengubah sesuatu yang drastis. Bagi saya, saya lebih suka tahu teknik command line sehingga, jika Apple mengubah sesuatu yang drastis, maka saya bisa terus berlari.
Volomike
5
$ pkgbuild --root ./HelloWorld.app salah (dengan anggapan bahwa .app adalah kumpulan aplikasi yang sebenarnya). pkgbuild beroperasi pada root tujuan: yaitu: folder yang berisi bundel yang dihasilkan oleh rantai alat xcode. Jadi argumen ke pkgbuild adalah path ke folder yang berisi bundel yang ingin kita paket. Gagal mendapatkan hak ini menghasilkan sebuah paket yang hanya berisi folder konten aplikasi. Itu tidak akan menginstal sebagai bundel aplikasi yang sebenarnya. Hadiahnya ada di komponen plist. Jika itu tidak mengandung entri RootRelativeBundlePath yang menentukan bundel aplikasi maka Anda telah mengacaukannya.
Jonathan Mitchell
185

Ada satu aplikasi yang sangat menarik oleh Stéphane Sudre yang melakukan semua ini untuk Anda, adalah skrip / mendukung bangunan dari baris perintah, memiliki GUI yang sangat bagus dan GRATIS. Yang menyedihkan adalah: itu disebut "Paket" yang membuatnya tidak mungkin ditemukan di google.

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

Saya berharap saya tahu tentang hal itu sebelum saya mulai membuat naskah saya sendiri.

Tangkapan layar aplikasi paket

Bram de Jong
sumber
11
Saya tidak percaya posting ini tidak memiliki poin lebih. Perangkat lunak itu luar biasa dan mendukung pembangunan dari baris perintah.
Cesar Mendoza
1
Adakah yang mencoba menandatangani paket dengan alat ini? Saya tidak bisa mendapatkan item menu "Set Certificate" untuk mengaktifkan ....
GTAE86
2
@ user283182: Benjolan yang sangat terlambat, pasti Anda sudah menemukan jawabannya, tetapi mungkin ini akan membantu orang lain - Saya pikir masalah yang Anda hadapi dirinci dalam [Pedoman Tinjauan Mac App Store] ( developer.apple.com/app- store / review / guidelines / mac /… ), aturan 2.14: "Aplikasi harus dikemas dan dikirim menggunakan teknologi pengemasan Apple yang termasuk dalam Xcode - tidak ada pemasang pihak ketiga yang diizinkan."
penatua
4
Saya berharap ini adalah aplikasi berbayar dan pengembang terus memperbarui dan menambal. Packages.app luar biasa terutama jika Anda ingin dengan cepat menyebarkan aplikasi Anda. Butuh waktu total 3 menit untuk menginstal, membaca Ikhtisar, mengatur proyek saya dan membuat paket yang dapat diinstal. Pujian besar untuk Stéphane.
Nikolay Christov
1
Aplikasi ini luar biasa!
Spencer Müller Diniz
3

FYI bagi mereka yang mencoba membuat penginstal paket untuk bundel atau plugin, mudah:

pkgbuild --component "Color Lists.colorPicker" --install-location ~/Library/ColorPickers ColorLists.pkg
gngrwzrd
sumber
2
FYI, ada perbedaan antara membuat .pkg dan membuat installer nyata dengan layar pembuka, lisensi, dan sebagainya.
catlan
ya saya sadar, saya meletakkan ini di sini karena saya tidak dapat menemukan referensi untuk membuat installer pkg untuk sebuah plugin.
gngrwzrd
Ini membuat saya berputar. Hanya minimum untuk memberi landasan.
uchuugaka
3

A +1 untuk jawaban yang diterima:

Seleksi Tujuan di Pemasang

Jika pemilihan domain (alias tujuan) diinginkan antara domain pengguna dan domain sistem daripada mencoba <domains enable_anywhere="true">menggunakan berikut:

<domains enable_currentUserHome="true" enable_localSystem="true"/>

enable_currentUserHome menginstal aplikasi aplikasi di bawah ~/Applications/dan enable_localSystemmemungkinkan aplikasi diinstal di bawah/Application

Saya sudah mencoba ini di El Capitan 10.11.6 (15G1217) dan tampaknya berfungsi dengan baik di mesin 1 dev dan 2 VM berbeda yang saya coba.

PnotNP
sumber
Ini bekerja dengan baik, tetapi dengan GOT'CHA: Jika Anda pertama kali menginstal per-pengguna, kemudian instal per-mesin, instal akan berada di dir-user, bukan dir-mesin, tetapi dengan hak sudo. Sebaliknya bukan itu masalahnya: Anda dapat menginstal per-mesin, dan kemudian per-pengguna setelah itu dan memilikinya di kedua tempat.
Terje Dahl
@ TerjeDahl ya ini karena pasca pemasangan bundel dipindahkan ke lokasi bundel id yang sama diinstal sebelumnya oleh installer (dan installer tahu itu). Ini dapat dicegah dengan beberapa pengaturan dalam file manifes yang saya tidak ingat sekarang.
PnotNP
@ PnotNP Ah. Jika Anda akan sangat baik untuk kembali dengan pengaturan itu jika Anda bisa mengingatnya, maka itu akan menjadi luar biasa!
Terje Dahl
2

Berikut ini skrip build yang membuat paket pemasang yang ditandatangani keluar dari build root.

#!/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
Doug Richardson
sumber
1
Ya, pkgbuild membuat pemasang .pkg.
Doug Richardson