Build Chain Setup

The basic tool to create a package is dpkg-buildpackage. But PBuilder creates packages in a minimal chroot, which ensures a clean build and enables us to build for multiple versions of multiple distributions, and even multiple architectures, all on a single build host. COWBuilder adds copy-on-write tactics to PBuilder, which saves significant amounts of time. And PDeBuild is a wrapper around either COWBuilder or PBuilder directly.

Into a package goes upstream source. But the packager may have to patch the source. And he certainly will have to adjust the package to its contents. For lack of a better word, I'll call the efforts of the packager the container here.

It is useful to keep the container under version control. Git being my VC-tool of choice, I use git-buildpackage to do that. So the list of tools, a simplified call graph if you will, becomes:

git-buildpackage -> pdebuild -> cowbuilder -> pbuilder -> dpkg-buildpackage

Procedure 2.2.  Setting up PBuilder/COWBuilder

  1. A ~/.pbuilderrc for multiple distributions

    Put the following in ~/.pbuilderrc. (It also works to put it in /etc/pbuilderrc.)

    # This is to enable building packages for multiple distributions
    
    # Change 'cowbuilder' to 'pbuilder' below if you prefer that
    PDEBUILD_PBUILDER=cowbuilder
    
    if [ -n "${DIST}" ]; then
        export DISTRIBUTION=$DIST
    
        AUTO_DEBSIGN=yes
    
        BASETGZ="$(dirname $BASETGZ)/$DIST-base.tgz"
    
        export BASEPATH=/var/cache/pbuilder/${DIST}-base.cow
        export BUILDPLACE=/var/cache/pbuilder/${DIST}.cow
    
        install -d ../lastbuild/${DIST}
        export BUILDRESULT=../lastbuild/${DIST}
    
        if echo $@|grep -qe --create ; then
            BUILDPLACE=/var/cache/pbuilder/${DIST}-base.cow
            install -d ${BUILDPLACE}
        fi  
    
        APTCACHE="/var/cache/pbuilder/$DIST/aptcache/"
    
        case ${DIST} in
            'lenny'|'squeeze'|'wheezy'|'sid' )
                MIRRORSITE=http://ftp.nl.debian.org/debian
                ;;
            'lucid'|'maverick'|'natty'|'oneiric'|'precise' )
                MIRRORSITE=http://osmirror.rug.nl/ubuntu
                ;;
        esac
    
    fi
    	    

  2. Creating COWBuilder chroots

    COWBuilder builds packages in chroot jails, which we need to create. Here's a script /usr/local/sbin/cowbuilder-create-base that will do it:

    
    #!/bin/bash
    
    declare DISTROS BP_ASIDE BUILDPLACE DIST DISTRO DEBOOTSRAPOPTS MIRROR PBUILDEROPTS
    declare CREATE=create
    
    PROGRAM=${0}
    OPTARGS=$(getopt -n $PROGRAM -o 'uh' -- "$@")
    eval set -- "$OPTARGS"
    while (( "$#" > "0" )) ; do
        case "$1" in
            '-h' )
                cat <<EOF
    
                usage: cowbuilder-create-base [-u] [dists]
    
                with -u meaning 'update instead of create' and
                [dists] a space separated list of common Debian or Ubuntu
                distribution codenames like 'precise' or 'squeeze'
    
    EOF
                exit 0
                ;;
            '-u' )
                shift 1
                CREATE=update
                ;;
            '--' )
                shift 1
                break
                ;;
            * )
                echo "unknown option: $1"
                exit 3
                ;;
        esac
    done   
    
    DISTROS=${@:-squeeze wheezy sid precise}
    
    restore_old_buildplace()
    {
        [ "${CREATE}" = "create" ] \
            && [ -n \"${BP_ASIDE}\" ] \
            && [ -d ${BP_ASIDE} ] \
            && rm -rf ${BUILDPLACE} \
            && mv ${BP_ASIDE} ${BUILDPLACE} \
            && return 0
        return 1
    }
    
    for DIST in ${DISTROS} ; do
        DEBOOTSTRAPOPTS=
        PBUILDEROPTS=
        case ${DIST} in
            hamm|slink|potato|woody|sarge|etch|lenny|squeeze|wheezy|sid )
                DISTRO=debian
                DEBOOTSTRAPOPTS="--debootstrapopts --keyring=/usr/share/keyrings/debian-archive-keyring.gpg"
                MIRROR=http://ftp.nl.debian.org/debian
                ;;
            hardy|lucid|maverick|natty|oneiric|precise )
                DISTRO=ubuntu
                MIRROR=http://osmirror.rug.nl/ubuntu
                PBUILDEROPTS="--components \"main universe\""
                ;;
            * )
                echo "unknown distro ${DIST}, please add it to the script before re-running"
                exit 2
        esac
    
        echo "Creating CowBuilder base for ${DISTRO} ${DIST}"
        BUILDPLACE=/var/cache/pbuilder/${DIST}-base.cow
    
        unset BP_ASIDE
        if [ "${CREATE}" = "create" ] ; then
            if [ -d "${BUILDPLACE}" ] ; then
                echo "Moving existing ${BUILDPLACE} aside to ${BP_ASIDE}"
                # If pbuilder fails, we want to restore this old original
                BP_ASIDE=$(mktemp -d --tmpdir=$(dirname ${BUILDPLACE}))
                mv ${BUILDPLACE} ${BP_ASIDE}
            fi
            install -d ${BUILDPLACE}
        fi
    
        trap restore_old_buildplace INT
    
        COMMAND="pbuilder --${CREATE} \
    --logfile pbuild-${DIST}-create.log \
    --buildplace ${BUILDPLACE} \
    --distribution ${DIST} \
    --mirror ${MIRROR} \
    --no-targz \
    --extrapackages cowdancer ${PBUILDEROPTS} \
    --debootstrap debootstrap ${DEBOOTSTRAPOPTS}"
    
        if eval ${COMMAND} ; then
            trap - INT
            [ "${CREATE}" = "create" ] && [ -n "${BP_ASIDE}" ] && [ -d ${BP_ASIDE} ] && rm -rf ${BP_ASIDE}
        else
            FAILLIST="${FAILLIST} ${DIST}"
            trap - INT
    
            if restore_old_buildplace ; then
                FAILLIST="${FAILLIST}(but existing version was saved and restored)"
                echo "The command \"${COMMAND}\" failed."
                echo "Old chroot restored from ${BP_ASIDE}"
            fi
    
        fi
    
    done
    
    
    if [ -n "${FAILLIST}" ] ; then
        echo "The following distributions failed to be (re)created: ${FAILLIST}"
        exit 1
    fi
    
    exit 0
    
    	    

    It can be called as either of these:

    apprentice@packaging-host:~$ sudo cowbuilder-create-base

    or

    apprentice@packaging-host:~$ sudo cowbuilder-create-base squeeze

    or

    apprentice@packaging-host:~$ sudo cowbuilder-create-base -u squeeze

    (The last one merely updates an existing chroot.)