el/dot-emacs.el (compile-command): Run compilations nice(1)ly by default.
[profile] / bin / mdw-build
CommitLineData
7ee12623
MW
1#! /bin/bash
2###
3### Build script for Debian packages
4###
5### (c) 2008 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This program is free software; you can redistribute it and/or modify
11### it under the terms of the GNU General Public License as published by
12### the Free Software Foundation; either version 2 of the License, or
13### (at your option) any later version.
14###
15### This program is distributed in the hope that it will be useful,
16### but WITHOUT ANY WARRANTY; without even the implied warranty of
17### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18### GNU General Public License for more details.
19###
20### You should have received a copy of the GNU General Public License
21### along with this program; if not, write to the Free Software Foundation,
22### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
85b7c21c
MW
24###--------------------------------------------------------------------------
25### Conventions for build systems.
26###
27### This script is designed to work with a variety of `make'-based build
28### systems, but there are a number of conventions which must be followed if
29### this is going to work properly.
30###
31### * There must be a `configure.ac', `configure.in', or `.links' file, or
32### a `.git' directory in the project top-level, so that we can find it.
33###
34### * The following `make' variables must be assigned in the top-level
35### Makefile, after `mdw-build' has constructed it.
36###
37### distdir The name of the top-level project directory in the
38### source distribution, and the base name for
39### distribution archives; should be of the form
40### `PROJECT-VERSION'.
41###
42### The following `make' targets must be available in the top-level
43### Makefile.
44###
45### dist Write to $(distdir).tar.gz a source distribution of
46### the package.
47###
48### distcheck As for `dist', but also build and test the project.
49###
50### * The source distribution constructed by `make dist' must contain a file
51### $(distdir)/RELEASE containing the release name. This isn't currently
52### tested, but it might be later.
53
7ee12623
MW
54set -e
55
56###--------------------------------------------------------------------------
816af8ee
MW
57### Configuration.
58
59unset checkout checkoutrev
60unset setup setupcmd
5a91acc5 61unset sign signkey
b94830d9 62unset sbuild sbuildsrv
5a91acc5 63unset upload uploadpath
816af8ee 64unset dput dputtarget
5a91acc5 65unset build distcheck debian clean vpath native
816af8ee
MW
66for i in \
67 "/etc/mdw-build.conf" \
68 "${XDG_CONFIG_HOME-$HOME/.config}/mdw-build.conf" \
69 "./.mdw-build.conf"
70do
71 if [ -f "$i" ]; then . "$i"; fi
72done
5a91acc5
MW
73default_depends () {
74 var=$1 want=$2
75 eval "p=\${$var+t} q=\${$want+t}"
76 case $p,$q in t,*) ;; *,t) eval "$var=yes" ;; *) eval "$var=no" ;; esac
77}
816af8ee
MW
78: ${checkout=yes} ${checkoutrev=HEAD}
79: ${build=test}
80: ${setup=yes} ${setupcmd=mdw-setup}
81: ${distcheck=yes}
82: ${debian=yes}
816af8ee
MW
83: ${clean=yes}
84: ${vpath=yes}
85: ${native=yes}
ac504698 86: ${make=make}
ff55a023 87: ${test=yes}
b94830d9 88default_depends sbuild sbuildsrv
5a91acc5
MW
89default_depends sign signkey
90default_depends upload uploadpath
91default_depends dput dputtarget
816af8ee
MW
92: ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS
93
94###--------------------------------------------------------------------------
7ee12623
MW
95### Parse options.
96
0660d224
MW
97prog=${0##*/}
98
7ee12623
MW
99usage () {
100 cat <<EOF
24a3095a 101Usage: $prog [-v] BUILDOPT
7ee12623
MW
102
103Build options:
104
105 [no]checkout[=REV]
106 [no]release
9c586ae1 107 [no]setup[=RUNE]
7ee12623
MW
108 [no]distcheck
109 [no]debian
5a91acc5
MW
110 [no]upload[=SERVER:PATH]
111 [no]dput[=TARGET]
7ee12623 112 [no]clean
f5b3423e 113 [no]vpath
b94830d9 114 [no]sbuild[=SERVER]
5a91acc5 115 [no]sign[=KEYID]
ff55a023 116 [no]test
d87d7867 117 [no]native
ac504698 118 make=MAKE
7ee12623
MW
119EOF
120}
121
122## Parse simple options.
123verbose=no
24a3095a 124while getopts "hv" opt; do
7ee12623
MW
125 case "$opt" in
126 h) usage; exit 0 ;;
127 v) verbose=yes ;;
128 *) exit 1 ;;
129 esac
130done
131shift $((OPTIND - 1))
132
133## Parse the build options.
5a91acc5
MW
134maybe_set () {
135 var=$1 want=$2
136 eval "p=\${$want+t}\${$want-nil}"
137 case $p in
138 t) eval $var=yes ;;
139 nil) echo >&2 "$prog: $want not set"; exit 1 ;;
140 esac
141}
7ee12623
MW
142for opt; do
143 case "$opt" in
144 checkout) checkout=yes checkoutrev=HEAD ;;
145 checkout=*) checkout=yes checkoutrev=${opt#*=} ;;
7ee12623
MW
146 release) build=release ;;
147 norelease) build=test ;;
9c586ae1
MW
148 setup) setup=yes setupcmd=mdw-setup ;;
149 setup=*) setup=yes setupcmd=${opt#*=} ;;
5a91acc5
MW
150 upload) maybe_set upload uploadpath ;;
151 upload=*) upload=yes uploadpath=${opt#*=} ;;
152 sign) maybe_set sign signkey ;;
153 sign=*) sign=yes signkey=${opt#*=} ;;
b94830d9
MW
154 sbuild) maybe_set sbuild sbuildsrv ;;
155 sbuild=*) sbuild=yes sbuildsrv=${opt#*=} ;;
5a91acc5
MW
156 dput) maybe_set dput dputtarget ;;
157 dput=*) dput=yes dputtarget=${opt#*=} ;;
ac504698 158 make=*) make=${opt#*=} ;;
5a91acc5 159
ff55a023 160 distcheck | debian | clean | vpath | native | test)
7ee12623
MW
161 eval "$opt=yes"
162 ;;
50c72b0f 163 nocheckout | nosetup | nodistcheck | nodebian | \
ff55a023 164 noupload | nodput | noclean | novpath | nonative | notest | \
1556faf7 165 nosbuild | nosign )
7ee12623
MW
166 eval "${opt#no}=no"
167 ;;
168 *)
169 usage >&2
170 exit 1
171 ;;
172 esac
173done
174
84dd9069
MW
175## Parse DEB_BUILD_OPTIONS.
176jobs=1
177set -- $DEB_BUILD_OPTIONS
178for opt; do
179 case "$opt" in
180 parallel=*) jobs=${opt#*=} ;;
ff55a023 181 nocheck) test=no ;;
84dd9069
MW
182 esac
183done
184
185makeopts=""
186case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac
187
7ee12623
MW
188###--------------------------------------------------------------------------
189### Utility functions.
190
190c1efc
MW
191## File descriptor assignments:
192##
193## 0 -- original stdin (never touched)
194## 1, 2 -- stdout, stderr, redirected to 3 while running comamnds
4ed33f50
MW
195## log -- logfile and original stderr (verbose), or logfile only (quiet);
196## captures command output
197## diag -- logfile; primary diagnostic output
ab9fae2a 198## term -- orginal stderr; secondary diagnostic output (with colours)
190c1efc 199
7ee12623
MW
200notify () {
201 colour=$1 message=$2
ab9fae2a
MW
202 echo $message >&$diag
203 echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&$term
7ee12623
MW
204}
205
206fail () {
207 notify 1 "!!! $*"
208 exit 1
209}
210
f282ba46
MW
211warn () {
212 case $build in
213 release) fail "$*" ;;
214 *) notify 5 "??? $*" ;;
215 esac
216}
217
7ee12623
MW
218info () {
219 notify 6 "--- $*"
220}
221
222assign () {
223 info "$1 = $2"
224 eval "$1=$2"
225}
226
227runx () {
228 notify 2 "+++ $*"
5b950572 229 nice "$@" 2>&$log {log}>&- {diag}>&- {term}>&- || fail "$1: exit $?"
7ee12623
MW
230}
231
ab9fae2a 232run () { runx "$@" >&$log; }
7ee12623
MW
233
234yesno () {
ab9fae2a
MW
235 echo -n "(test $*)" >&$diag
236 if "$@" >&$diag 2>&$diag {log}>&- {diag}>&- {term}>&-; then
237 echo "(yes)" >&$diag
7ee12623
MW
238 echo yes
239 else
ab9fae2a 240 echo "(no)" >&$diag
7ee12623
MW
241 echo no
242 fi
243}
244
245###--------------------------------------------------------------------------
246### Do the building.
247
ff55a023
MW
248## Some preflight checks.
249case $test,$build in
250 no,release) fail "refusing to make release build without testing" ;;
251esac
252case $test,$distcheck in
253 no,yes)
254 info "forcing \`distcheck' off because tsting disabled"
255 distcheck=no
256 ;;
257esac
258
7ee12623 259## Find the top-level package directory.
d43de82b
MW
260while [ ! -f configure.ac -a ! -f configure.in -a \
261 ! -f .links -a ! -d .git ]; do
7ee12623
MW
262 case "$(pwd)" in
263 /)
264 fail "couldn't find top-level directory"
265 ;;
266 esac
267 cd ..
268done
c3a2e2b1 269toppath=$(pwd)
7ee12623 270
9243a740
MW
271## Build any necessary qualifiers.
272qual= sep=.
273case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in
274 t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;;
275 t,*) fail "unknown build arch" ;;
276esac
277
7ee12623 278## Construct the output directory.
c3a2e2b1 279releasepath=$toppath/dist-$build$qual
47539e6a 280chmod -R +w $releasepath 2>/dev/null || :
7ee12623
MW
281rm -rf $releasepath 2>/dev/null || :
282mkdir $releasepath
4ed33f50 283logfile=$releasepath/mdw-build.log
5043931a 284exec {term}>&2
4ed33f50 285exec {diag}>>$logfile || fail "Failed to create log."
7ee12623 286case $verbose in
4ed33f50
MW
287 no) exec {log}>&$diag ;;
288 yes) exec {log}> >(tee -a $logfile >&$term {term}>&- {diag}>&-) ;;
7ee12623
MW
289esac
290
c3a2e2b1
MW
291## Repeat the earlier assignments for tbe benefit of the logfile.
292assign toppath $toppath
293assign releasepath $releasepath
4ed33f50 294assign logfile $logfile
c3a2e2b1 295
f282ba46 296## Do we have a Git repository?
be2a2314 297case "$checkout,$setup,$(yesno [ -d $toppath/.git ])" in
7ee12623
MW
298 yes,no,*)
299 fail "Inconsistent options: can't check out without setup."
300 ;;
301 yes,yes,no)
302 info "No Git repository found."
f282ba46 303 checkout=no gitver=none
7ee12623
MW
304 ;;
305 yes,yes,yes)
be2a2314 306 cd $toppath
7ee12623 307 [ "$(git ls-files -m)" = "" ] ||
f282ba46 308 warn "working tree has uncommitted changes"
66305913 309 ;;
f282ba46
MW
310esac
311
312## Is there Debian build equipment?
be2a2314 313case "$debian,$(yesno [ -d $toppath/debian ])" in
f282ba46
MW
314 yes,no)
315 info "No debian directory found."
316 debian=no debver=none
317 ;;
f0905f8c
MW
318 no,*)
319 debver=none
320 ;;
f282ba46 321 yes,yes)
ac1bda22 322 debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p')
40196145
MW
323 debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p')
324 debname=$(git config user.name) debemail=$(git config user.email)
f282ba46
MW
325 ;;
326esac
327
46fced9d
MW
328## Maybe check out a copy of the source.
329case "$checkout" in
330 yes)
331 cd $releasepath
be2a2314 332 run git clone -sn $toppath/.git _source
46fced9d
MW
333 assign srcpath $releasepath/_source
334 cd $srcpath
493856f1
MW
335 run git update-ref refs/heads/mdw-build $checkoutrev ""
336 run git symbolic-ref HEAD refs/heads/mdw-build
337 run git read-tree --reset refs/heads/mdw-build
338 run git checkout-index -afu
ac1bda22 339 assign gitversion "$(git describe --abbrev=4)"
46fced9d 340 ;;
be2a2314
MW
341 no)
342 assign srcpath $toppath
343 ;;
46fced9d
MW
344esac
345
f282ba46 346## Check the version number.
40196145 347hack_dch_p=no
ac1bda22 348case "$gitversion,$debver" in
f282ba46
MW
349 none,* | *,none)
350 ;;
351 *)
ac1bda22
MW
352 dvref=$(echo "$debver" | tr '~' '_')
353 if [ "$gitversion" = "$dvref" ]; then
354 assign debversion "$debver"
355 else
356 warn "Git version $gitversion doesn't match Debian version $debver"
40196145 357 hack_dch=yes
ac1bda22
MW
358 dver=$(echo $gitversion | sed 's/-/+/; s/-/./g')
359 case $debver in *~) dver=$debver$dver ;; esac
360 assign debversion "$dver"
361 now=$(date -R)
40196145 362 fi
f282ba46
MW
363 ;;
364esac
365
7ee12623
MW
366## Maybe refresh the build machinery.
367case "$setup" in
368 yes)
9c586ae1 369 run $setupcmd
7ee12623
MW
370 ;;
371esac
372
373## Initialize the build directory.
f5b3423e
MW
374case "$vpath,$(yesno [ -e $srcpath/configure ])" in
375 yes,yes)
376 assign buildpath $releasepath/_build
377 mkdir $buildpath
378 cd $buildpath
379 run $srcpath/configure
380 ;;
381 no,yes)
382 info "VPATH build disabled"
383 assign buildpath $srcpath
384 distcheck=no
385 cd $srcpath
386 run ./configure
387 ;;
388 *,no)
389 info "no configure script"
390 assign buildpath $srcpath
391 cd $srcpath
392 ;;
393esac
7ee12623
MW
394
395## Discover the release name.
396cat >find-distdir.mk <<'EOF'
397include Makefile
398print-distdir:
ab9fae2a 399 @echo >&$(fd) $(distdir)
7ee12623 400EOF
dd8d9a6c 401assign distdir \
ab9fae2a 402 $({ $make -f find-distdir.mk print-distdir fd=$t >/dev/null 2>&1; } {t}>&1)
7ee12623
MW
403
404## Get a tarball distribution.
405case "$distcheck" in
406 yes)
ac504698 407 run $make $makeopts distcheck
7ee12623
MW
408 ;;
409 no)
ac504698 410 run $make $makeopts dist
7ee12623
MW
411 ;;
412esac
413
414cd $releasepath
415
d87d7867
MW
416case $native in
417 yes)
418 if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE
419 then
420 fail "missing RELEASE file in distribution"
421 fi
422 ;;
423esac
7ee12623
MW
424
425run mv $buildpath/$distdir.tar.gz .
5a91acc5
MW
426case $build,$sign in
427 release,yes)
428 run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz
47f56ea2
MW
429 ;;
430esac
7ee12623
MW
431
432## Maybe build the Debian packages.
f282ba46
MW
433case "$debian" in
434 yes)
7ee12623
MW
435 run tar xvfz $distdir.tar.gz
436 cd $distdir
40196145
MW
437 case $hack_dch in
438 yes)
40196145 439 cat - debian/changelog >debian/changelog.new <<EOF
ac1bda22 440$debsrc ($debversion) experimental; urgency=low
40196145
MW
441
442 * Hacking in process, not intended for release.
443
444 -- $debname <$debemail> $now
445
446EOF
447 mv debian/changelog.new debian/changelog
448 ;;
449 esac
e5099dd8
MW
450 sbuildargs=$sbuildsrv
451 case $sbuild,$build in
452 yes,release)
453 case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac
454 ;;
6cf97414
MW
455 yes,*)
456 if [ -d $toppath/dist-$build.pkgs ]; then
457 sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs"
458 fi
459 ;;
e5099dd8 460 esac
ff55a023
MW
461 case "$sbuild,$test, $DEB_BUILD_OPTIONS " in
462 yes,no,*) sbuildargs="-T $sbuildargs" ;;
463 *" nocheck "*) ;;
464 no,no,*)
465 DEB_BUILD_OPTIONS=${DEB_BUILD_OPTIONS+"$DEB_BUILD_OPTIONS nocheck"}
466 ;;
467 esac
b94830d9 468 case $sbuild,$build,$sign in
e5099dd8 469 yes,*) run mdw-sbuild $sbuildargs ;;
b94830d9 470 no,release,yes) run dpkg-buildpackage -k$signkey ;;
5a91acc5
MW
471 no,*) run dpkg-buildpackage -us -uc ;;
472 esac
7ee12623
MW
473 ;;
474esac
475
476## Maybe upload Debian packages.
477cd $releasepath
478case "$upload,$build" in
5a91acc5
MW
479 yes,test) info "Test build: not uploading." ;;
480 yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;;
481esac
482case "$debian,$upload,$dput,$build" in
483 yes,yes,yes,release) run dput -f $dputtarget *.changes ;;
7ee12623
MW
484esac
485
486## Tidy up.
487case "$clean" in
488 yes)
489 rm -rf $releasepath/$distdir
490 rm -rf $releasepath/_source
491 rm -rf $releasepath/_build
492 ;;
493esac
494
495## Done.
496info "All OK."
497
498###----- That's all, folks --------------------------------------------------