Keywords: macOS | Installer | Developer ID | pkgbuild | productbuild
Abstract: This article provides a detailed guide on using pkgbuild, productbuild, and pkgutil to create macOS installer packages that comply with Gatekeeper requirements. Covering steps from component packages to product archives, including signing, script automation, and solutions to common issues, it is aimed at developers and system administrators.
With the introduction of macOS Gatekeeper security features, traditional tools like PackageMaker have become obsolete, requiring developers to switch to modern tools such as pkgbuild, productbuild, and pkgutil for building installer packages. This article will walk through the process of creating Developer ID-ready packages to ensure smooth distribution of applications on macOS systems.
Tool Overview
pkgbuild is used to create component packages containing the installation payload of applications; productbuild combines component packages into product archives and generates distribution definitions; pkgutil is used for manipulating package files, such as expanding or flattening. These tools are integrated with Xcode and accessible via the command line.
Creating Component Packages
First, use pkgbuild to analyze the application and generate a component property list. For example, for HelloWorld.app and Helper.app, run the command:
pkgbuild --analyze --root ./HelloWorld.app HelloWorldAppComponents.plist
Then, create the component package based on this list:
pkgbuild --root ./HelloWorld.app \
--component-plist HelloWorldAppComponents.plist \
HelloWorld.pkg
This ensures the package includes necessary metadata like identifier and version.
Building Product Archives
Use productbuild to synthesize a distribution definition file:
productbuild --synthesize \
--package HelloWorld.pkg --package Helper.pkg \
Distribution.xml
In Distribution.xml, you can customize elements such as title and license. Then, generate the final product archive:
productbuild --distribution ./Distribution.xml \
--package-path . \
./Installer.pkg
Signing the Installer Package
To pass Gatekeeper verification, sign the package using a Developer ID Installer certificate. Add the signature via productbuild or productsign, for example:
productsign --sign "Developer ID Installer: John Doe" \
./Installer.pkg ./SignedInstaller.pkg
Signing ensures the package originates from a trusted source, preventing user warnings.
Automation Scripts
Integrate into the Xcode build process by adding a run script phase. Create scripts in the project to automate package generation and signing. Example scripts include extracting version numbers and invoking pkgbuild and productbuild. Additionally, use scheme actions to copy packages into Xcode archives for distribution.
#!/bin/bash
VERSION=$(defaults read "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/Contents/Info" CFBundleVersion)
pkgbuild --root "${INSTALL_ROOT}" \
--identifier "com.example.pkg" \
--version "$VERSION" \
./Component.pkg
Special Considerations and Solutions
For Apple Silicon Macs, add the hostArchitectures option in the distribution definition:
<options hostArchitectures="arm64,x86_64" />
Common issues include destination selection panel bugs and limitations on home folder installations. It is recommended to avoid using domains enable_anywhere and instead use the rootVolumeOnly option for compatibility. RTFD files are not directly supported by productbuild; workarounds involve file replacement.
Supplementary Tools
Beyond command-line tools, third-party applications like Packages offer a graphical interface and scripting support, simplifying package creation. This is suitable for users who prefer GUI or rapid prototyping.
In summary, mastering pkgbuild and productbuild is essential for building macOS installer packages. By following the steps outlined here, developers can create secure, signable packages that meet modern system requirements.