3 ### Build a Debian package on supported architectures
5 ### (c) 2016 Mark Wooding
8 ###----- Licensing notice ---------------------------------------------------
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.
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.
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.
24 ###--------------------------------------------------------------------------
27 unset buildroot default_targets parallel
29 "/etc/mdw-sbuild.conf" \
30 "${XDG_CONFIG_HOME-$HOME/.config}/mdw-sbuild.conf"
32 if [ -f
"$i" ]; then .
"$i"; fi
34 : ${buildroot=$HOME/build}
35 : ${default_targets="wheezy-amd64 wheezy-i386"}
36 : ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS
38 ###--------------------------------------------------------------------------
43 fail
() { echo >&2 "$prog: $*"; exit 1; }
44 usage
() { echo "usage: $prog [-ain] [-t TARGET] COMMAND [ARGUMENTS ...]"; }
45 fail_usage
() { usage
>&2; exit 1; }
48 what
=$1 pat
=$2 type=$3; shift 3
50 [ $type "$i" ] || fail
"$what not found: \`$i'"
54 *) fail
"expected exactly one $what matching \`$pat', but found $#" ;;
68 while IFS
= read -r line
; do
69 printf "%-21s %c %s\n" "$tag" "$marker" "$line"
73 ###--------------------------------------------------------------------------
76 bogusp
=nil archp
=nil indepp
=nil keepon
=nil notreally
=nil
79 while getopts "haint:" opt
; do
86 -h Show this help text.
87 -a Build only architecture-dependent packages.
88 -i Build only architecture-neutral packages.
89 -k Keep going even if one fails.
90 -n Don't actually do the build.
91 -t TARGET Build in TARGET build environment.
96 Return a freshly-made directory for the source code to
100 Build the package placed in BUILDDIR, which should contain
101 exactly one \`.dsc' file, and whatever source archive files
110 t
) targets
="${targets+$targets }$OPTARG" ;;
114 shift $
(( $OPTIND - 1 ))
116 case $bogusp in t
) fail_usage
;; esac
117 case $archp,$indepp in nil
,nil
) archp
=t indepp
=t
;; esac
118 case ${targets+t} in t
) ;; *) targets
=$default_targets ;; esac
120 ###--------------------------------------------------------------------------
125 *,*,*) fail
"bad command name \`$1'" ;;
128 ## dirname PROJECT/VERSION
130 ## Try to create a fresh build directory.
132 case "$dist" in */*/*) fail
"bad distribution name \`$dist'" ;; esac
133 proj
=${dist%/*} ver
=${dist#*/}
139 while [ $i -lt
50 ]; do
142 ## Find a sequence number different from all of the existing builds of
145 for j
in "$ver#"*; do
146 case "$j" in "$ver#*") break ;; esac
148 if [ $nn -le
$n ]; then nn
=$
(( $n + 1 )); fi
151 ## Try to make the build directory. This might not work if we're
152 ## racing with another process, but that's why we're trying in a loop.
153 if mkdir
"$ver#$nn" >/dev
/null
2>&1; then
159 ## Make sure it actually failed because a directory appeared, rather
160 ## than for some other reason.
161 [ -e
"$ver#$nn" ] || \
162 fail
"unexpectedly couldn't create \`$buildroot/$dist#$nn'"
165 ## Make sure we actually succeeded.
166 case $winp in t
) ;; *) fail
"failed to create build directory" ;; esac
168 ## Make an empty directory for dependency packages.
172 echo "$buildroot/$dist#$nn"
176 echo >&2 "usage: $prog dir PROJECT/VERSION"; exit 1 ;;
181 ## Track down the build directory.
184 dsc
=$
(want_1
"file" "*.dsc" -f
*.dsc
)
186 ## Figure out which targets need building. If the `.dsc' file isn't
187 ## telling, assume it needs building everywhere and let sbuild(1) sort
189 os
=$
(dpkg-architecture
-qDEB_HOST_ARCH_OS
)
190 unset first rest
; anyp
=nil depp
=nil allp
=nil
191 wantarchs
=$
(sed -n
'/^[Aa]rchitecture:/ s/^[^:]*: *//p' "$dsc")
193 unset buildarchs buildarchs_seen
=:
195 ## Work through the available targets assigning builds to them. This is
196 ## actually a little tricky.
197 for t
in $targets; do
199 ## Dissect the target name.
200 suite
=${t%%-*} archs
=${t#*-}
202 */*) target
=${archs%/*} host=${archs#*/} ;;
203 *) target
=$archs host=$archs; t
=$suite-$target/$host ;;
205 case $buildarchs_seen in
209 buildarchs
=${buildarchs+$buildarchs }$target
210 buildarchs_seen
=$buildarchs_seen$target:
214 ## Work through the architectures which we can build.
215 for arch
in $wantarchs; do
218 ## Package suitable for all architectures.
220 ## If we don't want to build architecture-neutral packages then
221 ## there's nothing to do.
222 case $indepp in nil
) continue ;; esac
224 ## Pick this up if nobody has volunteered. However, we should be
225 ## ready to let some other architecture build this if it's going
226 ## to build some architecture-dependent package too.
227 case $anyp in nil
) first
=$t anyp
=t allp
=t
;; esac
230 ## There's at least one architecture-specific package.
232 ## If we don't want to build architecture-specific packages then
233 ## there's nothing to do.
234 case $archp in nil
) continue ;; esac
236 ## If we can't build it then we shouldn't try.
237 if ! dpkg-architecture
-a
"$os-$target" -i
"$arch"; then
241 ## Decide whether we should take responsibility for the
242 ## architecture-neutral packages. If nobody's claimed them yet,
243 ## or the previous claimant wasn't building architecture-specific
244 ## packages, we should take over.
246 nil
) first
=$t depp
=t anyp
=t
;;
247 t
) rest
="${rest+$rest }$t" ;;
254 ## If we never found a match then we can't do anything.
255 case $anyp in nil
) echo "$prog: no packages to build"; exit 0 ;; esac
257 ## Figure out the right options to use.
259 t
) firstopt
="--arch-all" ;;
260 nil
) firstopt
="--no-arch-all" ;;
264 nil
) firstopt
="$firstopt --no-arch-any" ;;
267 ## Sort out the additional packages. This is rather annoying, because
268 ## sbuild(1) does this in a really stupid way.
270 for a
in $buildarchs; do
272 for f
in $
(dpkg-scanpackages
-a
$a pkgs
/ |
273 sed -n
'/^Filename: /s///p')
279 ## Build the builds sequentially. Tests can conflict with each other,
280 ## e.g., over port numbers.
281 rc
=0 buildopt
=$firstopt
282 for t
in $first $rest; do
283 host=${t##*/} full
=${t%/*}
284 suite
=${full%%-*} target
=${full#*-}
286 ## And we're ready to go.
290 run sbuild
--extra-package
=$pkgs.
$target \
291 --dist
=$suite --build
=$host --host=$target \
292 --chroot
=$suite-$host --verbose
$buildopt $dsc \
296 decor
"$full" "|" >&4; } 2>&1 |
297 decor
"$full" "*" >&4; } 4>&1 |
298 cat -u
>&3; } 5>&1 </dev
/null
)
300 case $thisrc in 0) ;;
302 echo failed rc
=$thisrc >$stat; rc
=$thisrc
303 case $keepon in nil
) break ;; esac
306 buildopt
=--no-arch-all
311 echo >&2 "usage: $prog build BUILDDIR"; exit 1 ;;
314 fail
"unknown command \`$1'"
318 ###----- That's all, folks --------------------------------------------------