โครงการตัวอย่างของเรามีสองเป้าหมายการสร้าง: HelloWorld.app และ Helper.app เราทำแพคเกจส่วนประกอบสำหรับแต่ละและรวมไว้ในที่เก็บสินค้า
แพคเกจองค์ประกอบที่มีน้ำหนักบรรทุกที่จะติดตั้งโดยการติดตั้ง OS X แม้ว่าจะเป็นแพคเกจองค์ประกอบที่สามารถติดตั้งบนของตัวเองก็มักจะรวมอยู่ในที่เก็บสินค้า
หลังจาก "สร้างและเก็บถาวร" สำเร็จให้เปิด $ BUILT_PRODUCTS_DIR ในเทอร์มินัล
$ cd ~/Library/Developer/Xcode/DerivedData/.../InstallationBuildProductsLocation
$ pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
$ pkgbuild --analyze --root ./Helper.app HelperAppComponents.plist
นี้ทำให้เรามีองค์ประกอบ plist คุณจะพบคำอธิบายค่าในการที่"ตัวแทนรายการทรัพย์สิน"ส่วน pkgbuild -rootสร้างแพ็กเกจคอมโพเนนต์หากคุณไม่ต้องการเปลี่ยนคุณสมบัติดีฟอลต์ใด ๆ คุณสามารถละเว้นพารามิเตอร์--component-plistในคำสั่งต่อไปนี้
productbuild --synthesizeผลลัพธ์ในความหมายการจัดจำหน่าย
$ 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, ส่วนประกอบ, ทรัพยากรและสคริปต์
เพิ่มRun Script Build Phaseชื่อ "Generate Package" ซึ่งถูกตั้งค่าเป็นRun script เมื่อติดตั้งเท่านั้น :
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}"
หากคุณไม่ได้มีการเปลี่ยนแพคเกจหลังจากที่สร้างขึ้นด้วยproductbuildคุณสามารถกำจัดpkgutil --expand
และpkgutil --flatten
ขั้นตอน นอกจากนี้คุณสามารถใช้--sign paramenter บนproductbuildแทนที่จะวิ่งproductsign
ลงชื่อเข้าใช้ตัวติดตั้ง OS X
แพคเกจถูกเซ็นชื่อด้วยDeveloper ID Installerใบรับรองที่คุณสามารถดาวน์โหลดได้จากนักพัฒนาซอฟต์แวร์รับรองยูทิลิตี้
พวกเขาจะทำการลงนามกับ--sign "Developer ID Installer: John Doe"
พารามิเตอร์ของpkgbuild , productbuildหรือ productsign
โปรดทราบว่าถ้าคุณกำลังจะสร้างลงนามสินค้าที่เก็บโดยใช้ productbuild มีเหตุผลที่จะลงนามในไม่มีแพคเกจคอมโพเนนต์
ตลอดทาง: คัดลอกแพ็คเกจลงใน Xcode Archive
ในการคัดลอกบางสิ่งบางอย่างเข้าไปใน Xcode เอกสารเก่าเราไม่สามารถใช้เฟสรูปร่างเรียกใช้สคริปต์ สำหรับสิ่งนี้เราต้องใช้ Scheme Action
แก้ไข Scheme และขยายที่เก็บถาวร จากนั้นคลิกโพสต์แอ็คชันและเพิ่มแอ็คชันเรียกใช้สคริปต์ใหม่ :
ใน 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 Scheme ฉันแนะนำให้เพิ่มเป็น shell script ในโครงการของคุณเพื่อให้คุณสามารถกู้คืนการกระทำได้โดยการลากสคริปต์จากพื้นที่ทำงานไปยัง post-action
การเขียนสคริปต์
การสร้างสคริปต์มีสองประเภท: JavaScript ในไฟล์นิยามการแจกจ่ายและเชลล์สคริปต์
เอกสารที่ดีที่สุดเกี่ยวกับ Shell Scripts ที่พบในWhiteBox - PackageMaker How-toแต่อ่านด้วยความระมัดระวังเพราะมันอ้างถึงรูปแบบแพคเกจเก่า
อ่านเพิ่มเติม
ปัญหาที่ทราบและวิธีแก้ปัญหา
ปลายทางเลือกบานหน้าต่าง
ผู้ใช้มีตัวเลือกการเลือกปลายทางโดยมีเพียงตัวเลือกเดียว - "ติดตั้งสำหรับผู้ใช้ทุกคนของคอมพิวเตอร์เครื่องนี้" ตัวเลือกนั้นปรากฏขึ้นให้เลือกด้วยสายตา แต่ผู้ใช้จำเป็นต้องคลิกเพื่อดำเนินการติดตั้งต่อไปทำให้เกิดความสับสน
เอกสารประกอบของแอปเปิ้ลแนะนำให้ใช้ <domains enable_anywhere ... />
แต่สิ่งนี้จะเป็นตัวกระตุ้นให้เลือกบานหน้าต่างปลายทางที่ใหม่กว่าซึ่งแอปเปิ้ลไม่ได้ใช้ในแพ็คเกจใด ๆ
การใช้ค่าเสื่อมราคา<options rootVolumeOnly="true" />
จะให้ปลายทางเลือกบานหน้าต่างเก่าแก่คุณ
คุณต้องการติดตั้งรายการลงในโฟลเดอร์โฮมของผู้ใช้ปัจจุบัน
คำตอบสั้น ๆ : อย่าลอง!
คำตอบยาว: จริง ๆ ; อย่าลอง! อ่านปัญหาและวิธีแก้ไขตัวติดตั้งปัญหาการติดตั้งและวิธีการแก้ไขคุณรู้ไหมว่าฉันทำอะไรหลังจากอ่านข้อความนี้? ฉันโง่พอที่จะลอง บอกตัวเองฉันแน่ใจว่าพวกเขาแก้ไขปัญหาใน 10.7 หรือ 10.8
ก่อนอื่นที่ฉันเห็นเป็นครั้งคราวปลายทางที่กล่าวถึงเลือกบานหน้าต่างข้อผิดพลาด ที่ควรจะหยุดฉัน แต่ฉันไม่สนใจมัน หากคุณไม่ต้องการใช้เวลาหนึ่งสัปดาห์หลังจากที่คุณปล่อยซอฟต์แวร์ตอบรับการสนับสนุนทางอีเมลที่พวกเขาต้องคลิกเมื่อเลือกสีน้ำเงินที่ดีอย่าใช้สิ่งนี้
ตอนนี้คุณกำลังคิดว่าผู้ใช้ของคุณฉลาดพอที่จะคิดออกแผงใช่มั้ย ทีนี้นี่คืออีกเรื่องเกี่ยวกับการติดตั้งโฮมโฟลเดอร์พวกเขาไม่ทำงาน!
ฉันทดสอบเป็นเวลาสองสัปดาห์ในเครื่องที่แตกต่างกันประมาณ 10 เครื่องด้วยระบบปฏิบัติการที่แตกต่างกันและสิ่งใดที่มันไม่เคยล้มเหลว ดังนั้นฉันส่งมัน ภายในหนึ่งชั่วโมงของการเปิดตัวฉันเสียใจที่ผู้ใช้ไม่สามารถติดตั้งได้ บันทึกที่บอกใบ้ถึงปัญหาการอนุญาตที่คุณไม่สามารถแก้ไขได้
ลองทำซ้ำอีกครั้ง: เราไม่ได้ใช้ตัวติดตั้งสำหรับการติดตั้งโฟลเดอร์บ้าน!
RTFD สำหรับ Welcome, Read-me, License และข้อสรุปไม่เป็นที่ยอมรับ productbuild
อ่านฉันใบอนุญาตและข้อสรุปไม่ได้รับการยอมรับจาก
ตัวติดตั้งรองรับตั้งแต่ไฟล์ RTFD เริ่มต้นเพื่อสร้างหน้าจอต้อนรับด้วยรูปภาพ แต่การสร้างผลิตภัณฑ์ไม่ยอมรับ
วิธีแก้ปัญหา: ใช้ไฟล์ dummy rtf และแทนที่ในแพ็กเกจภายในเวลาไม่นาน productbuild
ทำเสร็จแล้ว
หมายเหตุ: คุณสามารถมีภาพ Retina ภายในไฟล์ RTFD ใช้หลายรูปแบบ TIFF 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
จำเป็นต้องเรียกใช้แอปในฐานะผู้ใช้ที่เข้าสู่ระบบไม่ใช่ในฐานะผู้ใช้โปรแกรมติดตั้ง นี้จะกระทำด้วยlaunchctl asuser เส้นทาง นอกจากนี้เราเพียงเรียกใช้มันเมื่อมันไม่ได้ติดตั้งบรรทัดคำสั่งทำได้ด้วยการติดตั้งเครื่องมือหรือแอปเปิ้ลสก์ท็อประยะไกล