X-Git-Url: https://git.distorted.org.uk/~mdw/profile/blobdiff_plain/98a2d95e575804674af77388f49b6ae27277a9b3..f173a9c272a79ac77dc896ab31cf445c48363956:/bin/mdw-build diff --git a/bin/mdw-build b/bin/mdw-build index d8be795..6c034b8 100755 --- a/bin/mdw-build +++ b/bin/mdw-build @@ -21,30 +21,107 @@ ### 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=!guess} +: ${distcheck=yes} +: ${debian=yes} +: ${clean=yes} +: ${vpath=yes} +: ${native=yes} +: ${make=make} +: ${test=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#*=} ;; - nocheckout) checkout=no ;; release) build=release ;; norelease) build=test ;; - - setup | distcheck | debian | upload | clean) + setup) setup=yes setupcmd=!guess ;; + 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#*=} ;; + make=*) make=${opt#*=} ;; + + distcheck | debian | clean | vpath | native | test) eval "$opt=yes" ;; - nosetup | nodistcheck | nodebian | noupload | noclean) + nocheckout | nosetup | nodistcheck | nodebian | \ + noupload | nodput | noclean | novpath | nonative | notest | \ + nosbuild | nosign ) eval "${opt#no}=no" ;; *) @@ -83,15 +172,35 @@ for opt; do esac done +## Parse DEB_BUILD_OPTIONS. +jobs=1 +set -- $DEB_BUILD_OPTIONS +for opt; do + case "$opt" in + parallel=*) jobs=${opt#*=} ;; + nocheck) test=no ;; + esac +done + +makeopts="" +case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac + ###-------------------------------------------------------------------------- ### Utility functions. -exec 3>&2 4>/dev/null 5>&2 +## File descriptor assignments: +## +## 0 -- original stdin (never touched) +## 1, 2 -- stdout, stderr, redirected to 3 while running comamnds +## log -- logfile and original stderr (verbose), or logfile only (quiet); +## captures command output +## diag -- logfile; primary diagnostic output +## term -- orginal stderr; secondary diagnostic output (with colours) notify () { colour=$1 message=$2 - echo $message >&4 - echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&5 + echo $message >&$diag + echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&$term } fail () { @@ -117,18 +226,18 @@ assign () { runx () { notify 2 "+++ $*" - "$@" 2>&3 || fail "$1: exit $?" + nice "$@" 2>&$log {log}>&- {diag}>&- {term}>&- || fail "$1: exit $?" } -run () { runx "$@" >&3; } +run () { runx "$@" >&$log; } yesno () { - echo -n "(test $*)" >&4 - if "$@" >&4 2>&4; then - echo "(yes)" >&4 + echo -n "(test $*)" >&$diag + if "$@" >&$diag 2>&$diag {log}>&- {diag}>&- {term}>&-; then + echo "(yes)" >&$diag echo yes else - echo "(no)" >&4 + echo "(no)" >&$diag echo no fi } @@ -136,8 +245,20 @@ yesno () { ###-------------------------------------------------------------------------- ### Do the building. +## Some preflight checks. +case $test,$build in + no,release) fail "refusing to make release build without testing" ;; +esac +case $test,$distcheck in + no,yes) + info "forcing \`distcheck' off because tsting disabled" + distcheck=no + ;; +esac + ## Find the top-level package directory. -while [ ! -f configure.ac -a ! -f configure.in -a ! -f .links ]; do +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" @@ -145,22 +266,35 @@ while [ ! -f configure.ac -a ! -f configure.in -a ! -f .links ]; do esac cd .. done -assign srcpath $(pwd) +toppath=$(pwd) + +## 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 +releasepath=$toppath/dist-$build$qual chmod -R +w $releasepath 2>/dev/null || : rm -rf $releasepath 2>/dev/null || : mkdir $releasepath +logfile=$releasepath/mdw-build.log +exec {term}>&2 +exec {diag}>>$logfile || fail "Failed to create log." case $verbose in - no) - exec 4>$releasepath/mdw-build.log 3>&4 || - fail "Failed to create log." - ;; + no) exec {log}>&$diag ;; + yes) exec {log}> >(tee -a $logfile >&$term {term}>&- {diag}>&-) ;; esac +## Repeat the earlier assignments for tbe benefit of the logfile. +assign toppath $toppath +assign releasepath $releasepath +assign logfile $logfile + ## Do we have a Git repository? -case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in +case "$checkout,$setup,$(yesno [ -d $toppath/.git ])" in yes,no,*) fail "Inconsistent options: can't check out without setup." ;; @@ -169,112 +303,194 @@ case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in checkout=no gitver=none ;; yes,yes,yes) - cd $srcpath + cd $toppath [ "$(git ls-files -m)" = "" ] || warn "working tree has uncommitted changes" - gitver=$(git describe) + ;; esac ## Is there Debian build equipment? -case "$debian,$(yesno [ -d $srcpath/debian ])" in +case "$debian,$(yesno [ -d $toppath/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') + debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p') + debname=$(git config user.name) debemail=$(git config user.email) ;; esac -## Check the version number. -case "$gitver,$debver" in - none,* | *,none) - ;; - *) - [ "$gitver" = "$debver" ] || - warn "Git version $gitver doesn't match Debian version $debver" - ;; -esac - -## Maybe check ot a copy of the source. +## Maybe check out a copy of the source. case "$checkout" in yes) cd $releasepath - run git clone -sn $srcpath/.git _source + run git clone -sn $toppath/.git _source assign srcpath $releasepath/_source cd $srcpath - run git checkout -b mdw-build $checkoutrev + run git update-ref refs/heads/mdw-build $checkoutrev "" + run git symbolic-ref HEAD refs/heads/mdw-build + run git read-tree --reset refs/heads/mdw-build + run git checkout-index -afu + assign gitversion "$(git describe --abbrev=4)" + ;; + no) + assign srcpath $toppath + ;; +esac + +## Check the version number. +hack_dch_p=no +case "$gitversion,$debver" in + none,* | *,none) + ;; + *) + dvref=$(echo "$debver" | tr '~' '_') + if [ "$gitversion" = "$dvref" ]; then + assign debversion "$debver" + else + warn "Git version $gitversion doesn't match Debian version $debver" + hack_dch=yes + dver=$(echo $gitversion | sed 's/-/+/; s/-/./g') + case $debver in *~) dver=$debver$dver ;; esac + assign debversion "$dver" + now=$(date -R) + fi ;; esac ## Maybe refresh the build machinery. case "$setup" in yes) - run mdw-setup + case $setupcmd in + !guess) + if [ -f .links ]; then setupcmd=mdw-setup + elif [ -x autogen.sh ]; then setupcmd=./autogen.sh + elif [ -x setup ]; then setupcmd=./setup + elif [ -f configure.ac ]; then setupcmd="autoreconf -is" + else setupcmd=mdw-setup + fi + ;; + esac + run $setupcmd ;; esac ## Initialize the build directory. -if [ -e $srcpath/configure ]; then - assign buildpath $releasepath/_build - mkdir $buildpath - cd $buildpath - run $srcpath/configure -else - info "no configure script" - assign buildpath $srcpath - cd $srcpath -fi +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 $(distdir) + @echo >&$(fd) $(distdir) EOF -assign distdir $(make -f find-distdir.mk print-distdir) +assign distdir \ + $({ $make -f find-distdir.mk print-distdir fd=$t >/dev/null 2>&1; } {t}>&1) ## Get a tarball distribution. case "$distcheck" in yes) - run make distcheck + run $make $makeopts distcheck ;; no) - run make dist + run $make $makeopts dist ;; esac cd $releasepath -if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE; then - fail "missing RELEASE file in distribution" -fi +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 - run dpkg-buildpackage -k$(mdw-conf releasekey) + case $hack_dch in + yes) + 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,$test, $DEB_BUILD_OPTIONS " in + yes,no,*) sbuildargs="-T $sbuildargs" ;; + *" nocheck "*) ;; + no,no,*) + DEB_BUILD_OPTIONS=${DEB_BUILD_OPTIONS+"$DEB_BUILD_OPTIONS nocheck"} + ;; + 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 \ - $(mdw-conf upload-target ftp.distorted.org.uk:~ftp/pub/mdw/) - case "$debian" in - yes) - run dput -f $(mdw-conf dput-target distorted) *.changes - ;; - esac + 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.