bin/mdw-build: Reflow the negated options list.
[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}
b94830d9 87default_depends sbuild sbuildsrv
5a91acc5
MW
88default_depends sign signkey
89default_depends upload uploadpath
90default_depends dput dputtarget
816af8ee
MW
91: ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS
92
93###--------------------------------------------------------------------------
7ee12623
MW
94### Parse options.
95
0660d224
MW
96prog=${0##*/}
97
7ee12623
MW
98usage () {
99 cat <<EOF
24a3095a 100Usage: $prog [-v] BUILDOPT
7ee12623
MW
101
102Build options:
103
104 [no]checkout[=REV]
105 [no]release
9c586ae1 106 [no]setup[=RUNE]
7ee12623
MW
107 [no]distcheck
108 [no]debian
5a91acc5
MW
109 [no]upload[=SERVER:PATH]
110 [no]dput[=TARGET]
7ee12623 111 [no]clean
f5b3423e 112 [no]vpath
b94830d9 113 [no]sbuild[=SERVER]
5a91acc5 114 [no]sign[=KEYID]
d87d7867 115 [no]native
ac504698 116 make=MAKE
7ee12623
MW
117EOF
118}
119
120## Parse simple options.
121verbose=no
24a3095a 122while getopts "hv" opt; do
7ee12623
MW
123 case "$opt" in
124 h) usage; exit 0 ;;
125 v) verbose=yes ;;
126 *) exit 1 ;;
127 esac
128done
129shift $((OPTIND - 1))
130
131## Parse the build options.
5a91acc5
MW
132maybe_set () {
133 var=$1 want=$2
134 eval "p=\${$want+t}\${$want-nil}"
135 case $p in
136 t) eval $var=yes ;;
137 nil) echo >&2 "$prog: $want not set"; exit 1 ;;
138 esac
139}
7ee12623
MW
140for opt; do
141 case "$opt" in
142 checkout) checkout=yes checkoutrev=HEAD ;;
143 checkout=*) checkout=yes checkoutrev=${opt#*=} ;;
7ee12623
MW
144 release) build=release ;;
145 norelease) build=test ;;
9c586ae1
MW
146 setup) setup=yes setupcmd=mdw-setup ;;
147 setup=*) setup=yes setupcmd=${opt#*=} ;;
5a91acc5
MW
148 upload) maybe_set upload uploadpath ;;
149 upload=*) upload=yes uploadpath=${opt#*=} ;;
150 sign) maybe_set sign signkey ;;
151 sign=*) sign=yes signkey=${opt#*=} ;;
b94830d9
MW
152 sbuild) maybe_set sbuild sbuildsrv ;;
153 sbuild=*) sbuild=yes sbuildsrv=${opt#*=} ;;
5a91acc5
MW
154 dput) maybe_set dput dputtarget ;;
155 dput=*) dput=yes dputtarget=${opt#*=} ;;
ac504698 156 make=*) make=${opt#*=} ;;
5a91acc5
MW
157
158 distcheck | debian | clean | vpath | native)
7ee12623
MW
159 eval "$opt=yes"
160 ;;
50c72b0f 161 nocheckout | nosetup | nodistcheck | nodebian | \
1556faf7
MW
162 noupload | nodput | noclean | novpath | nonative | \
163 nosbuild | nosign )
7ee12623
MW
164 eval "${opt#no}=no"
165 ;;
166 *)
167 usage >&2
168 exit 1
169 ;;
170 esac
171done
172
84dd9069
MW
173## Parse DEB_BUILD_OPTIONS.
174jobs=1
175set -- $DEB_BUILD_OPTIONS
176for opt; do
177 case "$opt" in
178 parallel=*) jobs=${opt#*=} ;;
179 esac
180done
181
182makeopts=""
183case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac
184
7ee12623
MW
185###--------------------------------------------------------------------------
186### Utility functions.
187
190c1efc
MW
188## File descriptor assignments:
189##
190## 0 -- original stdin (never touched)
191## 1, 2 -- stdout, stderr, redirected to 3 while running comamnds
4ed33f50
MW
192## log -- logfile and original stderr (verbose), or logfile only (quiet);
193## captures command output
194## diag -- logfile; primary diagnostic output
ab9fae2a 195## term -- orginal stderr; secondary diagnostic output (with colours)
190c1efc 196
7ee12623
MW
197notify () {
198 colour=$1 message=$2
ab9fae2a
MW
199 echo $message >&$diag
200 echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&$term
7ee12623
MW
201}
202
203fail () {
204 notify 1 "!!! $*"
205 exit 1
206}
207
f282ba46
MW
208warn () {
209 case $build in
210 release) fail "$*" ;;
211 *) notify 5 "??? $*" ;;
212 esac
213}
214
7ee12623
MW
215info () {
216 notify 6 "--- $*"
217}
218
219assign () {
220 info "$1 = $2"
221 eval "$1=$2"
222}
223
224runx () {
225 notify 2 "+++ $*"
5b950572 226 nice "$@" 2>&$log {log}>&- {diag}>&- {term}>&- || fail "$1: exit $?"
7ee12623
MW
227}
228
ab9fae2a 229run () { runx "$@" >&$log; }
7ee12623
MW
230
231yesno () {
ab9fae2a
MW
232 echo -n "(test $*)" >&$diag
233 if "$@" >&$diag 2>&$diag {log}>&- {diag}>&- {term}>&-; then
234 echo "(yes)" >&$diag
7ee12623
MW
235 echo yes
236 else
ab9fae2a 237 echo "(no)" >&$diag
7ee12623
MW
238 echo no
239 fi
240}
241
242###--------------------------------------------------------------------------
243### Do the building.
244
245## Find the top-level package directory.
d43de82b
MW
246while [ ! -f configure.ac -a ! -f configure.in -a \
247 ! -f .links -a ! -d .git ]; do
7ee12623
MW
248 case "$(pwd)" in
249 /)
250 fail "couldn't find top-level directory"
251 ;;
252 esac
253 cd ..
254done
c3a2e2b1 255toppath=$(pwd)
7ee12623 256
9243a740
MW
257## Build any necessary qualifiers.
258qual= sep=.
259case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in
260 t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;;
261 t,*) fail "unknown build arch" ;;
262esac
263
7ee12623 264## Construct the output directory.
c3a2e2b1 265releasepath=$toppath/dist-$build$qual
47539e6a 266chmod -R +w $releasepath 2>/dev/null || :
7ee12623
MW
267rm -rf $releasepath 2>/dev/null || :
268mkdir $releasepath
4ed33f50 269logfile=$releasepath/mdw-build.log
5043931a 270exec {term}>&2
4ed33f50 271exec {diag}>>$logfile || fail "Failed to create log."
7ee12623 272case $verbose in
4ed33f50
MW
273 no) exec {log}>&$diag ;;
274 yes) exec {log}> >(tee -a $logfile >&$term {term}>&- {diag}>&-) ;;
7ee12623
MW
275esac
276
c3a2e2b1
MW
277## Repeat the earlier assignments for tbe benefit of the logfile.
278assign toppath $toppath
279assign releasepath $releasepath
4ed33f50 280assign logfile $logfile
c3a2e2b1 281
f282ba46 282## Do we have a Git repository?
be2a2314 283case "$checkout,$setup,$(yesno [ -d $toppath/.git ])" in
7ee12623
MW
284 yes,no,*)
285 fail "Inconsistent options: can't check out without setup."
286 ;;
287 yes,yes,no)
288 info "No Git repository found."
f282ba46 289 checkout=no gitver=none
7ee12623
MW
290 ;;
291 yes,yes,yes)
be2a2314 292 cd $toppath
7ee12623 293 [ "$(git ls-files -m)" = "" ] ||
f282ba46 294 warn "working tree has uncommitted changes"
66305913 295 ;;
f282ba46
MW
296esac
297
298## Is there Debian build equipment?
be2a2314 299case "$debian,$(yesno [ -d $toppath/debian ])" in
f282ba46
MW
300 yes,no)
301 info "No debian directory found."
302 debian=no debver=none
303 ;;
f0905f8c
MW
304 no,*)
305 debver=none
306 ;;
f282ba46 307 yes,yes)
ac1bda22 308 debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p')
40196145
MW
309 debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p')
310 debname=$(git config user.name) debemail=$(git config user.email)
f282ba46
MW
311 ;;
312esac
313
46fced9d
MW
314## Maybe check out a copy of the source.
315case "$checkout" in
316 yes)
317 cd $releasepath
be2a2314 318 run git clone -sn $toppath/.git _source
46fced9d
MW
319 assign srcpath $releasepath/_source
320 cd $srcpath
493856f1
MW
321 run git update-ref refs/heads/mdw-build $checkoutrev ""
322 run git symbolic-ref HEAD refs/heads/mdw-build
323 run git read-tree --reset refs/heads/mdw-build
324 run git checkout-index -afu
ac1bda22 325 assign gitversion "$(git describe --abbrev=4)"
46fced9d 326 ;;
be2a2314
MW
327 no)
328 assign srcpath $toppath
329 ;;
46fced9d
MW
330esac
331
f282ba46 332## Check the version number.
40196145 333hack_dch_p=no
ac1bda22 334case "$gitversion,$debver" in
f282ba46
MW
335 none,* | *,none)
336 ;;
337 *)
ac1bda22
MW
338 dvref=$(echo "$debver" | tr '~' '_')
339 if [ "$gitversion" = "$dvref" ]; then
340 assign debversion "$debver"
341 else
342 warn "Git version $gitversion doesn't match Debian version $debver"
40196145 343 hack_dch=yes
ac1bda22
MW
344 dver=$(echo $gitversion | sed 's/-/+/; s/-/./g')
345 case $debver in *~) dver=$debver$dver ;; esac
346 assign debversion "$dver"
347 now=$(date -R)
40196145 348 fi
f282ba46
MW
349 ;;
350esac
351
7ee12623
MW
352## Maybe refresh the build machinery.
353case "$setup" in
354 yes)
9c586ae1 355 run $setupcmd
7ee12623
MW
356 ;;
357esac
358
359## Initialize the build directory.
f5b3423e
MW
360case "$vpath,$(yesno [ -e $srcpath/configure ])" in
361 yes,yes)
362 assign buildpath $releasepath/_build
363 mkdir $buildpath
364 cd $buildpath
365 run $srcpath/configure
366 ;;
367 no,yes)
368 info "VPATH build disabled"
369 assign buildpath $srcpath
370 distcheck=no
371 cd $srcpath
372 run ./configure
373 ;;
374 *,no)
375 info "no configure script"
376 assign buildpath $srcpath
377 cd $srcpath
378 ;;
379esac
7ee12623
MW
380
381## Discover the release name.
382cat >find-distdir.mk <<'EOF'
383include Makefile
384print-distdir:
ab9fae2a 385 @echo >&$(fd) $(distdir)
7ee12623 386EOF
dd8d9a6c 387assign distdir \
ab9fae2a 388 $({ $make -f find-distdir.mk print-distdir fd=$t >/dev/null 2>&1; } {t}>&1)
7ee12623
MW
389
390## Get a tarball distribution.
391case "$distcheck" in
392 yes)
ac504698 393 run $make $makeopts distcheck
7ee12623
MW
394 ;;
395 no)
ac504698 396 run $make $makeopts dist
7ee12623
MW
397 ;;
398esac
399
400cd $releasepath
401
d87d7867
MW
402case $native in
403 yes)
404 if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE
405 then
406 fail "missing RELEASE file in distribution"
407 fi
408 ;;
409esac
7ee12623
MW
410
411run mv $buildpath/$distdir.tar.gz .
5a91acc5
MW
412case $build,$sign in
413 release,yes)
414 run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz
47f56ea2
MW
415 ;;
416esac
7ee12623
MW
417
418## Maybe build the Debian packages.
f282ba46
MW
419case "$debian" in
420 yes)
7ee12623
MW
421 run tar xvfz $distdir.tar.gz
422 cd $distdir
40196145
MW
423 case $hack_dch in
424 yes)
40196145 425 cat - debian/changelog >debian/changelog.new <<EOF
ac1bda22 426$debsrc ($debversion) experimental; urgency=low
40196145
MW
427
428 * Hacking in process, not intended for release.
429
430 -- $debname <$debemail> $now
431
432EOF
433 mv debian/changelog.new debian/changelog
434 ;;
435 esac
e5099dd8
MW
436 sbuildargs=$sbuildsrv
437 case $sbuild,$build in
438 yes,release)
439 case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac
440 ;;
6cf97414
MW
441 yes,*)
442 if [ -d $toppath/dist-$build.pkgs ]; then
443 sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs"
444 fi
445 ;;
e5099dd8 446 esac
b94830d9 447 case $sbuild,$build,$sign in
e5099dd8 448 yes,*) run mdw-sbuild $sbuildargs ;;
b94830d9 449 no,release,yes) run dpkg-buildpackage -k$signkey ;;
5a91acc5
MW
450 no,*) run dpkg-buildpackage -us -uc ;;
451 esac
7ee12623
MW
452 ;;
453esac
454
455## Maybe upload Debian packages.
456cd $releasepath
457case "$upload,$build" in
5a91acc5
MW
458 yes,test) info "Test build: not uploading." ;;
459 yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;;
460esac
461case "$debian,$upload,$dput,$build" in
462 yes,yes,yes,release) run dput -f $dputtarget *.changes ;;
7ee12623
MW
463esac
464
465## Tidy up.
466case "$clean" in
467 yes)
468 rm -rf $releasepath/$distdir
469 rm -rf $releasepath/_source
470 rm -rf $releasepath/_build
471 ;;
472esac
473
474## Done.
475info "All OK."
476
477###----- That's all, folks --------------------------------------------------