ReleaseEngineering/PuppetAgain/HowTo/Build DMGs

From MozillaWiki
Jump to: navigation, search

DMGs Stink

DMG's cannot be uninstalled. They are unversioned, with no notion of "ugprades". They do not handle any dependencies. But, they're what we have.

They also don't, by default, do a good job of being compatible between major versions of OS X. So we generally build a DMG for a particular version on a host running that version. If we need the same DMG for multiple versions, it gets built multiple times. The builds generally use exactly the same shell script.

Summary

We build DMGs using shell scripts, with those shell scripts checked in at modules/packages/manifests/mozilla/*-dmg.sh. For most DMGs, we build using the same script on all relevant versions of OS X, to ensure compatibility. Some packages are explicitly multi-version compatible, and those are generally built on a current-generation builder machine.

When a package is upgraded, a new version of the script should be included in the puppet patch. This ensures that we always have the capacity to rebuild packages (modulo the vagaries of Xcode versions, OS versions, etc.), and also makes upgrades easier as they can start from a known state.

Newer scripts get all of their prerequisites directly. Some older scripts require a copy of the corresponding srpm be unpacked with bsdtar. We should try to rewrite such older scripts as we come across them.

Requirements

You'll need:

  • bsdtar (only for extracting srpms; should be on the system to begin with)
  • gcc (from XCode)
  • either
    • packagemaker
      • install: from repos/private/packagemaker-4.4.dmg, or just from XCode-4.4)
    • pkgbuild
      • install: part of system installation for 10.7+ and I believe 10.6.6+
      • note: acts as a replacement for packagemaker (packagemaker appears to not have been updated in +2 years)

Building A Package

There are shell scripts to build every custom DMG from the corresponding RPM sources, in hg. They are named $package-dmg.sh.

For newer scripts, you should just be able to download the script on a system with the appropriate version of OS X and of XCode, and run it. Older scripts will require an SRPM be unpacked first.

How do I Make Packages?

pkgbuilder seems to be preferred, but a lot of the scripts still use packagemaker. Your choice.

Where do I Run It?

(bhearsum used mac-depsigning1 the last time he had to build a package. it seemed like a safe place to screw around.)

At the moment, the answer to this question has been lost to time. Check bugs, and ask people. If there are existing DMGs for each OS X version, then most likely each was built on that OS X version. In general, we have one version of Xcode that we know how to install for each version of OS X (defined in puppet), so that's the Xcode that was used.

Add something like this to the script to eliminate ambiguity in the future:

# ensure the same build environment (you can change this if necessary, just test carefully)
if [ ! -x /tools/packagemaker/bin/packagemaker ]; then
    echo "install the packagemaker package (also in puppetagain)"
    exit 1
fi

if [ "$(sw_vers -productVersion)" != "$osx_vers" ]; then
    echo "Build this on a $osx_vers host"
    exit 1
fi

if [ "$(xcodebuild -version | grep Xcode)" != "Xcode $xcode_vers" ]; then
    echo "Build this with Xcode $xcode_vers"
    exit 1
fi

Unpacking an SRPM

In a fresh new directory, get a copy of the corresponding src.rpm from http://puppetagain.pub.build.mozilla.org/data, and run

bsdtar -xf whatever.src.rpm

it should unpack a tarball, a spec file, and maybe some patches.

Building A Package That Depends On Another

This is pretty annoying. You need to find a temporary machine where you can install the first (depended-upon) package, that also has all of the requirements installed.

Installing a Package

You can install DMGs with

   packages::pkgdmg {
       pkgname:
           version => "version";
   }

note that the version *must* match exactly that given in the name of the DMG, and that the OS version will be included in the URL path unless you pass os_version_specific => false.