#! /bin/bash ### ### Build script for Debian packages ### ### (c) 2008 Mark Wooding ### ###----- Licensing notice --------------------------------------------------- ### ### This program is free software; you can redistribute it and/or modify ### it under the terms of the GNU General Public License as published by ### the Free Software Foundation; either version 2 of the License, or ### (at your option) any later version. ### ### This program is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ### GNU General Public License for more details. ### ### You should have received a copy of the GNU General Public License ### along with this program; if not, write to the Free Software Foundation, ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ###-------------------------------------------------------------------------- ### Conventions for build systems. ### ### This script is designed to work with a variety of `make'-based build ### systems, but there are a number of conventions which must be followed if ### this is going to work properly. ### ### * There must be a `configure.ac', `configure.in', or `.links' file, or ### a `.git' directory in the project top-level, so that we can find it. ### ### * The following `make' variables must be assigned in the top-level ### Makefile, after `mdw-build' has constructed it. ### ### distdir The name of the top-level project directory in the ### source distribution, and the base name for ### distribution archives; should be of the form ### `PROJECT-VERSION'. ### ### The following `make' targets must be available in the top-level ### Makefile. ### ### dist Write to $(distdir).tar.gz a source distribution of ### the package. ### ### distcheck As for `dist', but also build and test the project. ### ### * The source distribution constructed by `make dist' must contain a file ### $(distdir)/RELEASE containing the release name. This isn't currently ### tested, but it might be later. set -e ###-------------------------------------------------------------------------- ### Configuration. unset checkout checkoutrev unset setup setupcmd unset sign signkey unset sbuild sbuildsrv unset upload uploadpath unset dput dputtarget unset build distcheck debian clean vpath native for i in \ "/etc/mdw-build.conf" \ "${XDG_CONFIG_HOME-$HOME/.config}/mdw-build.conf" \ "./.mdw-build.conf" do if [ -f "$i" ]; then . "$i"; fi done default_depends () { var=$1 want=$2 eval "p=\${$var+t} q=\${$want+t}" case $p,$q in t,*) ;; *,t) eval "$var=yes" ;; *) eval "$var=no" ;; esac } : ${checkout=yes} ${checkoutrev=HEAD} : ${build=test} : ${setup=yes} ${setupcmd=mdw-setup} : ${distcheck=yes} : ${debian=yes} : ${clean=yes} : ${vpath=yes} : ${native=yes} default_depends sbuild sbuildsrv default_depends sign signkey default_depends upload uploadpath default_depends dput dputtarget : ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS ###-------------------------------------------------------------------------- ### Parse options. prog=${0##*/} usage () { cat <&2 "$prog: $want not set"; exit 1 ;; esac } for opt; do case "$opt" in checkout) checkout=yes checkoutrev=HEAD ;; checkout=*) checkout=yes checkoutrev=${opt#*=} ;; release) build=release ;; norelease) build=test ;; setup) setup=yes setupcmd=mdw-setup ;; setup=*) setup=yes setupcmd=${opt#*=} ;; upload) maybe_set upload uploadpath ;; upload=*) upload=yes uploadpath=${opt#*=} ;; sign) maybe_set sign signkey ;; sign=*) sign=yes signkey=${opt#*=} ;; sbuild) maybe_set sbuild sbuildsrv ;; sbuild=*) sbuild=yes sbuildsrv=${opt#*=} ;; dput) maybe_set dput dputtarget ;; dput=*) dput=yes dputtarget=${opt#*=} ;; distcheck | debian | clean | vpath | native) eval "$opt=yes" ;; nocheckout | nosetup | nodistcheck | nodebian | \ noupload | nodput | noclean | novpath | nonative | nosbuild | nosign) eval "${opt#no}=no" ;; *) usage >&2 exit 1 ;; esac done ## Parse DEB_BUILD_OPTIONS. jobs=1 set -- $DEB_BUILD_OPTIONS for opt; do case "$opt" in parallel=*) jobs=${opt#*=} ;; esac done makeopts="" case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac ###-------------------------------------------------------------------------- ### Utility functions. exec 3>&2 4>/dev/null 5>&2 notify () { colour=$1 message=$2 echo $message >&4 echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&5 } fail () { notify 1 "!!! $*" exit 1 } warn () { case $build in release) fail "$*" ;; *) notify 5 "??? $*" ;; esac } info () { notify 6 "--- $*" } assign () { info "$1 = $2" eval "$1=$2" } runx () { notify 2 "+++ $*" "$@" 2>&3 || fail "$1: exit $?" } run () { runx "$@" >&3; } yesno () { echo -n "(test $*)" >&4 if "$@" >&4 2>&4; then echo "(yes)" >&4 echo yes else echo "(no)" >&4 echo no fi } ###-------------------------------------------------------------------------- ### Do the building. ## Find the top-level package directory. while [ ! -f configure.ac -a ! -f configure.in -a \ ! -f .links -a ! -d .git ]; do case "$(pwd)" in /) fail "couldn't find top-level directory" ;; esac cd .. done assign toppath $(pwd) assign srcpath $toppath ## Build any necessary qualifiers. qual= sep=. case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;; t,*) fail "unknown build arch" ;; esac ## Construct the output directory. assign releasepath $srcpath/dist-$build$qual chmod -R +w $releasepath 2>/dev/null || : rm -rf $releasepath 2>/dev/null || : mkdir $releasepath case $verbose in no) exec 4>$releasepath/mdw-build.log 3>&4 || fail "Failed to create log." ;; esac ## Do we have a Git repository? case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in yes,no,*) fail "Inconsistent options: can't check out without setup." ;; yes,yes,no) info "No Git repository found." checkout=no gitver=none ;; yes,yes,yes) cd $srcpath [ "$(git ls-files -m)" = "" ] || warn "working tree has uncommitted changes" ;; esac ## Is there Debian build equipment? case "$debian,$(yesno [ -d $srcpath/debian ])" in yes,no) info "No debian directory found." debian=no debver=none ;; no,*) debver=none ;; yes,yes) debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p' | tr \~ -) debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p') debname=$(git config user.name) debemail=$(git config user.email) ;; esac ## Maybe check out a copy of the source. case "$checkout" in yes) cd $releasepath run git clone -sn $srcpath/.git _source assign srcpath $releasepath/_source cd $srcpath run git checkout -b mdw-build $checkoutrev gitver=$(git describe --abbrev=4) ;; esac ## Check the version number. hack_dch_p=no case "$gitver,$debver" in none,* | *,none) ;; *) if [ "$gitver" != "$debver" ]; then warn "Git version $gitver doesn't match Debian version $debver" hack_dch=yes fi ;; esac ## Maybe refresh the build machinery. case "$setup" in yes) run $setupcmd ;; esac ## Initialize the build directory. case "$vpath,$(yesno [ -e $srcpath/configure ])" in yes,yes) assign buildpath $releasepath/_build mkdir $buildpath cd $buildpath run $srcpath/configure ;; no,yes) info "VPATH build disabled" assign buildpath $srcpath distcheck=no cd $srcpath run ./configure ;; *,no) info "no configure script" assign buildpath $srcpath cd $srcpath ;; esac ## Discover the release name. cat >find-distdir.mk <<'EOF' include Makefile print-distdir: @echo >&3 $(distdir) EOF assign distdir \ $({ make -f find-distdir.mk print-distdir >/dev/null 2>&1; } 3>&1) ## Get a tarball distribution. case "$distcheck" in yes) run make $makeopts distcheck ;; no) run make $makeopts dist ;; esac cd $releasepath case $native in yes) if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE then fail "missing RELEASE file in distribution" fi ;; esac run mv $buildpath/$distdir.tar.gz . case $build,$sign in release,yes) run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz ;; esac ## Maybe build the Debian packages. case "$debian" in yes) run tar xvfz $distdir.tar.gz cd $distdir case $hack_dch in yes) dver=$(echo $gitver | sed 's/-/+/; s/-/./g') now=$(date -R) cat - debian/changelog >debian/changelog.new < $now EOF mv debian/changelog.new debian/changelog ;; esac sbuildargs=$sbuildsrv case $sbuild,$build in yes,release) case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac ;; yes,*) if [ -d $toppath/dist-$build.pkgs ]; then sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs" fi ;; esac case $sbuild,$build,$sign in yes,*) run mdw-sbuild $sbuildargs ;; no,release,yes) run dpkg-buildpackage -k$signkey ;; no,*) run dpkg-buildpackage -us -uc ;; esac ;; esac ## Maybe upload Debian packages. cd $releasepath case "$upload,$build" in yes,test) info "Test build: not uploading." ;; yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;; esac case "$debian,$upload,$dput,$build" in yes,yes,yes,release) run dput -f $dputtarget *.changes ;; esac ## Tidy up. case "$clean" in yes) rm -rf $releasepath/$distdir rm -rf $releasepath/_source rm -rf $releasepath/_build ;; esac ## Done. info "All OK." ###----- That's all, folks --------------------------------------------------