Question

I've been attempting to port a Mac PackageMaker command line build to pkgbuild and productbuild but I'm stuck. Unfortunately I haven't found much of anything documenting how these new programs work except for this StackOverflow post and the pkgbuild and productbuild man pages.

Here's my problem. I've created a root install directory that has the following files in it:

/some_path/Applications
                       /MyProgram.app
          /Library
                  /Frameworks
                             /MyFramework.framework
                                                   /[library files...]

The command line call below worked great for PackageMaker. It created an installer that installed all of the files above.

$ /Developer/usr/bin/packagemaker \
    --title "My Program" \
    --root /some_path \
    --version 1.0.0 \
    --filter "\.DS_Store" \
    --resources ./resources/ \
    --scripts ./scripts/ \
    --root-volume-only \
    --domain system \
    --verbose \
    --no-relocate \
    --target 10.5 \
    --id com.my_company.pkg \
    --out MyProgram.pkg

Now I'm trying to write this with pkgbuild and having a major problem. I use the following call:

$ pkgbuild \
    --root /some_path \
    --version 1.0.0 \
    --install-location "/" \
    --scripts "./scripts/" \
    --identifier "com.my_company.pkg" \
    MyProgram.pkg

This command builds an installer that copies the MyProgram.framework directory into /Library/Frameworks. However it does not install the MyProgram.app file into the /Applications directory. When I look at the installer logs I see this message:

Applications/MyProgram.app relocated to /some_path/Applications/MyProgram.app

Can anyone shed some light on why this isn't adding the MyProgram.app file into the /Applications directory like PackageMaker was doing?

Was it helpful?

Solution

Unfortunately the answer to this question wasn't exactly what I was looking for. I couldn't figure out how to eliminate PackageMaker from the process. However there is a solution that includes pkgutil along with PackageMaker to create an installer with custom welcome message, license and background image entirely on the command line. The PackageMaker GUI is NOT required. The steps are as follows:

  1. Run the packagemaker command line executable on the special directory structure. This directory structure reflects the Mac file system. Read more in the old but reliable "PackageMaker How-to" tutorial.
  2. Run pkgutil (pkgutil --expand) to extract the package contents
  3. Take a look at the contents and identify what you want to alter. Some options are the welcome message, license and background image.
  4. Add commands to alter these files via the command line. Review the "Automating Apple's PackageMaker" tutorial for more information. The easiest way is just to run something like this echo '<background file="your_background.png">'.
  5. Run pkgutil (pkgutil --flatten) to rebuild the package.

OTHER TIPS

First of all, are you sure that you need an installer? You could put the framework inside the application. The Installer and pkgbuild are a bit flaky, to say the least.

Now to the problem at hand: Relocation has to do with the fact that a user could move the Application from /Applications to say /WorkApplications /PrivateApplications. In your case the Installer probably finds your Application in the build folder and installs it over this one.

I think the Installer uses the Application Bundle Identifier and Spotlight for the relocation, so for testing you could add the build folder to the Spotlight ignore list.

You can define in the Component Property List BundleIsRelocatable. If you really have to install a framework global, this is one bundle where you want to set BundleIsRelocatable to false.

The question you reference has pretty much everything you need to eliminate Package Maker entirely. One thing I added is to use sed after the productbuild --synthesize ... invocation to insert lines into the distribution file. For example, here are some Terminal commands I use once I've already built the component package:

productbuild --synthesize --package "components/SubPackage.pkg" "distribution.xml"
sed -i "" \
-e '$ i\
\    <title>Installer Title</title>' \
-e '$ i\
\    <background file="background.png" alignment="left" scaling="proportional" />' \
-e '$ i\
\    <welcome file="welcome.rtf" />' \
"distribution.xml"
productbuild --distribution "distribution.xml" --resources "resources/" --package-path "components/" "Installer.pkg"

This avoids having to use pkgutil --expand and pkgutil --flatten to modify the installer.

Create component plist file, which has value for relocatable property.

pkgbuild --analyze --root "$dst_src_root" "$installer_root/Components.plist"

Edit component plist and Set "BundleIsRelocatable" to false. This is done one time in my project, as installer contents does not change (One application and one plugin). I am reusing same component plist everytime to create contents package.

sudo pkgbuild --root "$dst_src_root" --component-plist "$installer_root/Components.plist" --identifier "com.company.app" --version "1.0" --scripts "$dst_scpt_root" "$dst_pkg_root/InstallPackage/cisContents.pkg" 

Then using productbuild, we can create final package

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top