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