Create PKG Installers from Homebrew Formulas
brew-pkg is a Homebrew external command that builds macOS installer packages from Homebrew formulas. The formula must first already be installed on the system.
First, add the brew-pkg formulae tap:
brew tap timsutton/formulae
Then install it:
brew install brew-pkg
Creating a Package
Assuming the formula ntfs-3g is already installed:
brew pkg ntfs-3g
The output will be something like:
MTeam7 [~] $ brew pkg --with-deps --without-kegs ntfs-3g ==> Creating package staging root using Homebrew prefix /usr/local ==> Staging formula ntfs-3g ==> Staging formula pkg-config ==> Staging formula gettext ==> Building package ntfs-3g-2017.3.23_1.pkg Mteam7 [~] $ ls ntfs-3g-2017.3.23_1.pkg 9.0M -rw-r--r-- 1 Mteam7 staff 9.0M Aug 11 23:44 ntfs-3g-2017.3.23_1.pkg Mteam7 [~] $ lsbom $(pkgutil --bom ntfs-3g-2017.3.23_1.pkg) | head -30 . 40700 0/0 ./usr 40755 0/0 ./usr/local 40755 0/0 ./usr/local/.brew 40755 0/0 ./usr/local/.brew/gettext.rb 100644 0/0 1487 3776327809 ./usr/local/.brew/ntfs-3g.rb 100644 0/0 2510 363375937 ./usr/local/bin 40755 0/0 ./usr/local/bin/autopoint 100555 0/0 27026 164851193 ./usr/local/bin/envsubst 100555 0/0 39592 2668043940 ./usr/local/bin/gettext 100555 0/0 39308 2298554039 ./usr/local/bin/gettext.sh 100555 0/0 5190 3488949678 ./usr/local/bin/gettextize 100555 0/0 42298 3448148383 ./usr/local/bin/lowntfs-3g 100555 0/0 61952 3749278950 ./usr/local/bin/msgattrib 100555 0/0 28304 3131124536 ./usr/local/bin/msgcat 100555 0/0 28412 1398000252 ./usr/local/bin/msgcmp 100555 0/0 29248 133122482 ./usr/local/bin/msgcomm 100555 0/0 28408 3242228031 ./usr/local/bin/msgconv 100555 0/0 27952 2052481136 ./usr/local/bin/msgen 100555 0/0 27960 2829033349 ./usr/local/bin/msgexec 100555 0/0 27520 3583181032 ./usr/local/bin/msgfilter 100555 0/0 33548 1504121072 ./usr/local/bin/msgfmt 100555 0/0 80120 1675568021 ./usr/local/bin/msggrep 100555 0/0 10916 1305508188 ./usr/local/bin/msginit 100555 0/0 48892 1109971268 ./usr/local/bin/msgmerge 100555 0/0 58928 2435734692 ./usr/local/bin/msgunfmt 100555 0/0 38612 5012713 ./usr/local/bin/msguniq 100555 0/0 28224 1131948277 ./usr/local/bin/ngettext 100555 0/0 39332 4164570214 ./usr/local/bin/ntfs-3g 100555 0/0 56552 3583091600 ./usr/local/bin/ntfs-3g.probe 100555 0/0 13460 527138039
Usage: brew pkg [--identifier-prefix] [--with-deps] [--without-kegs] formula Build an OS X installer package from a formula. It must be already installed; 'brew pkg' doesn't handle this for you automatically. The '--identifier-prefix' option is strongly recommended in order to follow the conventions of OS X installer packages. Options: --identifier-prefix set a custom identifier prefix to be prepended to the built package's identifier, ie. 'org.nagios' makes a package identifier called 'org.nagios.nrpe' --with-deps include all the package's dependencies in the built package --without-kegs exclude package contents at /usr/local/Cellar/packagename --scripts set the path to custom preinstall and postinstall scripts
If a formula has defined a launchd plist, brew-pkg will also install this to the package's root in /Library/LaunchDaemons.
By default behaviour brew pkg include all package kegs located in /usr/local/Cellar/packagename. If you need to exclude it, specify option --without-kegs
You can set the path to custom preinstall and postinstall scripts with the --scripts option which is just literally passed through to the pkgbuild command. If this directory contains scripts named preinstall and/or postinstall, these will be run as the top-level scripts of the package.
Pkgbuild's Script Help
--scripts scripts-path Archive the entire contents of scripts-path as the package scripts. If this directory contains scripts named preinstall and/or postinstall, these will be run as the top-level scripts of the package. If you want to run scripts for spe- cific bundles, you must specify those in a component property list; see more at COMPONENT PROPERTY LIST. Any other files under scripts-path will be used only if the top-level or com- ponent-specific scripts invoke them. COMPONENT PROPERTY LIST When you package a destination root, you can use a component property list to specify how bundles in that root should be handled by the OS X Installer. This property list should be an array of dictionaries, where each dictionary specifies a single bundle. The dictionary keys are as follows: Key Description RootRelativeBundlePath Path to bundle relative to the destination root (string) BundleIsRelocatable Install bundle over previous version if moved by user? (bool) BundleIsVersionChecked Don't install bundle if newer version on disk? (bool) BundleHasStrictIdentifier Require identical bundle identifiers at install path? (bool) BundleOverwriteAction How to treat existing on-disk version of bundle (string) BundlePreInstallScriptPath Relative path to bundle-specific preinstall script BundlePostInstallScriptPath Relative path to bundle-specific postinstall script ChildBundles Bundles under this bundle (array of dictionaries) The easiest way to create a component property list is to use the --analyze option and point pkgbuild at your current destination root. The output will be a component property list with default attributes, which you can then edit as needed. You can also specify a previous version of your component property list when using --analyze, which will cause the attributes of previously existing bundles to be propagated forward. BundleOverwriteAction specifies how an existing version of the bundle on disk should be handled when the version in the package is installed. If you specify upgrade, the bundle in the package atomically replaces any version on disk; this has the effect of deleting old paths that no longer exist in the new version of the bundle. If you specify update, the bun- dle in the package overwrites the version on disk, and any files not con- tained in the package will be left intact; this is appropriate when you are delivering an update-only package. Another effect of update is that the package bundle will not be installed at all if there is not already a version on disk; this allows a package to deliver an update for an app that the user might have deleted. BundlePreInstallScriptPath and BundlePostInstallScriptPath are meaningful only if --scripts was used to specify a scripts directory. The paths given by these keys must be relative to the scripts directory. ChildBundles can be used to represent nesting of bundles, but it does not change the meaning of RootRelativeBundlePath within lower-level dictio- naries (i.e. it is always relative to the destination root). If you write a component property list manually, you do not need to use ChildBundles at all; you can simply put all bundle dictionaries in the top-level array.