bin/mdw-build: Allow overriding the `make' program.
[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 | \
b94830d9 162 noupload | nodput | noclean | novpath | nonative | nosbuild | nosign)
7ee12623
MW
163 eval "${opt#no}=no"
164 ;;
165 *)
166 usage >&2
167 exit 1
168 ;;
169 esac
170done
171
84dd9069
MW
172## Parse DEB_BUILD_OPTIONS.
173jobs=1
174set -- $DEB_BUILD_OPTIONS
175for opt; do
176 case "$opt" in
177 parallel=*) jobs=${opt#*=} ;;
178 esac
179done
180
181makeopts=""
182case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac
183
7ee12623
MW
184###--------------------------------------------------------------------------
185### Utility functions.
186
187exec 3>&2 4>/dev/null 5>&2
188
189notify () {
190 colour=$1 message=$2
191 echo $message >&4
192 echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&5
193}
194
195fail () {
196 notify 1 "!!! $*"
197 exit 1
198}
199
f282ba46
MW
200warn () {
201 case $build in
202 release) fail "$*" ;;
203 *) notify 5 "??? $*" ;;
204 esac
205}
206
7ee12623
MW
207info () {
208 notify 6 "--- $*"
209}
210
211assign () {
212 info "$1 = $2"
213 eval "$1=$2"
214}
215
216runx () {
217 notify 2 "+++ $*"
218 "$@" 2>&3 || fail "$1: exit $?"
219}
220
221run () { runx "$@" >&3; }
222
223yesno () {
224 echo -n "(test $*)" >&4
225 if "$@" >&4 2>&4; then
226 echo "(yes)" >&4
227 echo yes
228 else
229 echo "(no)" >&4
230 echo no
231 fi
232}
233
234###--------------------------------------------------------------------------
235### Do the building.
236
237## Find the top-level package directory.
d43de82b
MW
238while [ ! -f configure.ac -a ! -f configure.in -a \
239 ! -f .links -a ! -d .git ]; do
7ee12623
MW
240 case "$(pwd)" in
241 /)
242 fail "couldn't find top-level directory"
243 ;;
244 esac
245 cd ..
246done
b9ad2dae
MW
247assign toppath $(pwd)
248assign srcpath $toppath
7ee12623 249
9243a740
MW
250## Build any necessary qualifiers.
251qual= sep=.
252case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in
253 t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;;
254 t,*) fail "unknown build arch" ;;
255esac
256
7ee12623 257## Construct the output directory.
9243a740 258assign releasepath $srcpath/dist-$build$qual
47539e6a 259chmod -R +w $releasepath 2>/dev/null || :
7ee12623
MW
260rm -rf $releasepath 2>/dev/null || :
261mkdir $releasepath
262case $verbose in
263 no)
264 exec 4>$releasepath/mdw-build.log 3>&4 ||
265 fail "Failed to create log."
266 ;;
267esac
268
f282ba46 269## Do we have a Git repository?
7ee12623
MW
270case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in
271 yes,no,*)
272 fail "Inconsistent options: can't check out without setup."
273 ;;
274 yes,yes,no)
275 info "No Git repository found."
f282ba46 276 checkout=no gitver=none
7ee12623
MW
277 ;;
278 yes,yes,yes)
279 cd $srcpath
280 [ "$(git ls-files -m)" = "" ] ||
f282ba46 281 warn "working tree has uncommitted changes"
66305913 282 ;;
f282ba46
MW
283esac
284
285## Is there Debian build equipment?
286case "$debian,$(yesno [ -d $srcpath/debian ])" in
287 yes,no)
288 info "No debian directory found."
289 debian=no debver=none
290 ;;
f0905f8c
MW
291 no,*)
292 debver=none
293 ;;
f282ba46 294 yes,yes)
ac1bda22 295 debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p')
40196145
MW
296 debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p')
297 debname=$(git config user.name) debemail=$(git config user.email)
f282ba46
MW
298 ;;
299esac
300
46fced9d
MW
301## Maybe check out a copy of the source.
302case "$checkout" in
303 yes)
304 cd $releasepath
305 run git clone -sn $srcpath/.git _source
306 assign srcpath $releasepath/_source
307 cd $srcpath
493856f1
MW
308 run git update-ref refs/heads/mdw-build $checkoutrev ""
309 run git symbolic-ref HEAD refs/heads/mdw-build
310 run git read-tree --reset refs/heads/mdw-build
311 run git checkout-index -afu
ac1bda22 312 assign gitversion "$(git describe --abbrev=4)"
46fced9d
MW
313 ;;
314esac
315
f282ba46 316## Check the version number.
40196145 317hack_dch_p=no
ac1bda22 318case "$gitversion,$debver" in
f282ba46
MW
319 none,* | *,none)
320 ;;
321 *)
ac1bda22
MW
322 dvref=$(echo "$debver" | tr '~' '_')
323 if [ "$gitversion" = "$dvref" ]; then
324 assign debversion "$debver"
325 else
326 warn "Git version $gitversion doesn't match Debian version $debver"
40196145 327 hack_dch=yes
ac1bda22
MW
328 dver=$(echo $gitversion | sed 's/-/+/; s/-/./g')
329 case $debver in *~) dver=$debver$dver ;; esac
330 assign debversion "$dver"
331 now=$(date -R)
40196145 332 fi
f282ba46
MW
333 ;;
334esac
335
7ee12623
MW
336## Maybe refresh the build machinery.
337case "$setup" in
338 yes)
9c586ae1 339 run $setupcmd
7ee12623
MW
340 ;;
341esac
342
343## Initialize the build directory.
f5b3423e
MW
344case "$vpath,$(yesno [ -e $srcpath/configure ])" in
345 yes,yes)
346 assign buildpath $releasepath/_build
347 mkdir $buildpath
348 cd $buildpath
349 run $srcpath/configure
350 ;;
351 no,yes)
352 info "VPATH build disabled"
353 assign buildpath $srcpath
354 distcheck=no
355 cd $srcpath
356 run ./configure
357 ;;
358 *,no)
359 info "no configure script"
360 assign buildpath $srcpath
361 cd $srcpath
362 ;;
363esac
7ee12623
MW
364
365## Discover the release name.
366cat >find-distdir.mk <<'EOF'
367include Makefile
368print-distdir:
dd8d9a6c 369 @echo >&3 $(distdir)
7ee12623 370EOF
dd8d9a6c 371assign distdir \
ac504698 372 $({ $make -f find-distdir.mk print-distdir >/dev/null 2>&1; } 3>&1)
7ee12623
MW
373
374## Get a tarball distribution.
375case "$distcheck" in
376 yes)
ac504698 377 run $make $makeopts distcheck
7ee12623
MW
378 ;;
379 no)
ac504698 380 run $make $makeopts dist
7ee12623
MW
381 ;;
382esac
383
384cd $releasepath
385
d87d7867
MW
386case $native in
387 yes)
388 if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE
389 then
390 fail "missing RELEASE file in distribution"
391 fi
392 ;;
393esac
7ee12623
MW
394
395run mv $buildpath/$distdir.tar.gz .
5a91acc5
MW
396case $build,$sign in
397 release,yes)
398 run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz
47f56ea2
MW
399 ;;
400esac
7ee12623
MW
401
402## Maybe build the Debian packages.
f282ba46
MW
403case "$debian" in
404 yes)
7ee12623
MW
405 run tar xvfz $distdir.tar.gz
406 cd $distdir
40196145
MW
407 case $hack_dch in
408 yes)
40196145 409 cat - debian/changelog >debian/changelog.new <<EOF
ac1bda22 410$debsrc ($debversion) experimental; urgency=low
40196145
MW
411
412 * Hacking in process, not intended for release.
413
414 -- $debname <$debemail> $now
415
416EOF
417 mv debian/changelog.new debian/changelog
418 ;;
419 esac
e5099dd8
MW
420 sbuildargs=$sbuildsrv
421 case $sbuild,$build in
422 yes,release)
423 case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac
424 ;;
6cf97414
MW
425 yes,*)
426 if [ -d $toppath/dist-$build.pkgs ]; then
427 sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs"
428 fi
429 ;;
e5099dd8 430 esac
b94830d9 431 case $sbuild,$build,$sign in
e5099dd8 432 yes,*) run mdw-sbuild $sbuildargs ;;
b94830d9 433 no,release,yes) run dpkg-buildpackage -k$signkey ;;
5a91acc5
MW
434 no,*) run dpkg-buildpackage -us -uc ;;
435 esac
7ee12623
MW
436 ;;
437esac
438
439## Maybe upload Debian packages.
440cd $releasepath
441case "$upload,$build" in
5a91acc5
MW
442 yes,test) info "Test build: not uploading." ;;
443 yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;;
444esac
445case "$debian,$upload,$dput,$build" in
446 yes,yes,yes,release) run dput -f $dputtarget *.changes ;;
7ee12623
MW
447esac
448
449## Tidy up.
450case "$clean" in
451 yes)
452 rm -rf $releasepath/$distdir
453 rm -rf $releasepath/_source
454 rm -rf $releasepath/_build
455 ;;
456esac
457
458## Done.
459info "All OK."
460
461###----- That's all, folks --------------------------------------------------