]> git.pld-linux.org Git - projects/cleanbuild.git/blob - cleanbuild
- su is now in util-linux
[projects/cleanbuild.git] / cleanbuild
1 #!/usr/bin/sudo /bin/sh
2
3 RPMS_FROM="$HOME/rpm/cleanRPMS.repo"
4 DEST="th"
5 SRC="-n th-x86_64-test"
6 SUFFIX=""
7 CACHEDIR="$PWD/poldekcache"
8 RPMMACROS=""
9 BUILDERRC=""
10 IGNORE=""
11 CHROOTSIZE="4G"
12 ignore() { IGNORE="$IGNORE $*"; }
13 NODEBUG=true
14 CLEANAFTER=false
15 FORCE_UMOUNT=false
16 NOREBUILDDB=true
17 # Whatever you set here as value, consider that it may not be shorter than
18 # /usr/lib/debug (or /usr/src/debug) for debuginfo to work.
19 # You get "Only dest dir longer than base dir not supported" error otherwise.
20 BUILDDIR=/usr/src/BUILD
21
22 [ -r .cleanbuildrc ] && . ./.cleanbuildrc
23
24 [ -z "$USER" ] && echo "USER not defined" && exit 1
25 [ "$USER" = "root" ] && echo "USER must not be root" && exit 1
26
27 export LC_ALL=C
28 unset LANGUAGE
29 unset LANG
30
31 usage() {
32         [ $# -gt 0 ] && echo "$*"
33         echo "Usage:"
34         echo "  ./cleanbuild [cleanbuild options] specname [builder options]"
35         echo "  ./build [cleanbuild options] specname [builder options]"
36         echo "  ./clean [cleanbuild options]"
37         echo "  ./create [cleanbuild options]"
38         echo "  ./install [cleanbuild options] packages"
39         echo ""
40         echo "cleanbuild options:"
41         echo " -32, -64, -th-i486  - select architecture"
42         echo " --cleanafter | -ca  - clean after build"
43         echo " --forceumount | -fu - force umount tmpfs"
44         echo " --debug             - enable debug"
45         echo " -a, -b, -c, -d, -e  - select alternative chroot directory"
46         exit 1
47 }
48
49 FETCH=false
50 CLEAN=false
51 CREATE=false
52 BUILD=false
53 INSTALL=false
54
55 case "$0" in
56         *clean)
57                 CLEAN=exit_after
58                 ;;
59         *cleanbuild)
60                 FETCH=true
61                 CLEAN=true
62                 CREATE=true
63                 BUILD=true
64                 ;;
65         *build)
66                 CREATE=true
67                 BUILD=true
68                 ;;
69         *create)
70                 CLEAN=true
71                 CREATE=exit_after
72                 ;;
73         *install)
74                 CREATE=true
75                 INSTALL=exit_after
76                 ;;
77         *)
78                 usage
79                 ;;
80 esac
81
82 while [ $# -gt 0 ]; do
83         OPT="${1}"
84         case "$OPT" in
85                 -32)    OPT="-th-i686" ;;
86                 -64)    OPT="-th-x86_64" ;;
87                 -th-32) OPT="-th-i686" ;;
88                 -th-64) OPT="-th-x86_64" ;;
89                 -ti-32) OPT="-ti-i686" ;;
90                 -ti-64) OPT="-ti-x86_64" ;;
91                 -ac)    OPT="-ac-amd64" ;;
92                 -ac-32) OPT="-ac-i586" ;;
93                 -ac-64) OPT="-ac-amd64" ;;
94         esac
95
96         V="${OPT#-}"
97         case "$OPT" in
98                 -th-i[46]86 | -th-x86_64)
99                         DEST="$V"
100                         SRC="-n $V-ready"
101                         ;;
102                 -th-i[46]86-test | -th-x86_64-test)
103                         DEST="$V"
104                         SRC="-n $V"
105                         ;;
106                 -ti-i[56]86 | -ti-x86_64)
107                         DEST="$V"
108                         SRC="-n $V-ready"
109                         ;;
110                 -ti-i[56]86-test | -ti-x86_64-test)
111                         DEST="$V"
112                         SRC="-n $V"
113                         ;;
114                 -ac-amd64 | -ac-i[356]86 | -ac-athlon)
115                         DEST="$V"
116                         SRC="-n $V-ready"
117                         ;;
118                 -[1-9]G | -[1-9][0-9]G )
119                         CHROOTSIZE="$V"
120                         ;;
121                 --cleanafter | -ca)
122                         CLEANAFTER=true
123                         ;;
124                 --debug)
125                         NODEBUG=false
126                         ;;
127                 --forceumount | -fu)
128                         FORCE_UMOUNT=true
129                         ;;
130                 -[a-e])
131                         SUFFIX="$OPT"
132                         ;;
133                 -~*)
134                         SUFFIX="$V"
135                         ;;
136                 *)
137                         break
138                         ;;
139         esac
140         shift
141 done
142
143 if $BUILD; then
144         [ $# -ne 0 ] || usage
145         build_pkg="${1}"
146         build_pkg="${build_pkg%/}"
147         build_pkg="${build_pkg%.spec}"
148         build_pkg="${build_pkg#*/}"
149         shift
150
151         builder_options="$*"
152 fi
153
154 $NODEBUG || set -x
155
156 CHNAME="chroot-$DEST$SUFFIX"
157 CHDIR="$PWD/$CHNAME"
158 CHHOME="/home/users/$USER"
159
160 warn()
161 {
162         echo -n -e "\033[31;1m" >&2
163         echo -n "$*" >&2
164         echo -e "\033[0m" >&2
165 }
166
167 die()
168 {
169         code=$1
170         shift
171         warn "$*"
172         exit $code
173 }
174
175 info()
176 {
177         echo -n -e "\033[32m"
178         echo -n "$*"
179         echo -e "\033[0m"
180 }
181
182 title()
183 {
184         [ -t 1 ] || return 0
185         local msg="$CHNAME: $build_pkg: $*"
186         case "$TERM" in
187                 cygwin|xterm*)
188                         echo -ne "\033]1;$msg\007\033]2;$msg\007" >&2
189                         ;;
190                 screen*)
191                         echo -ne "\033]0;$msg\007" >&2
192                         ;;
193         esac
194         return 0
195 }
196
197 exit_after()
198 {
199         return 0;
200 }
201
202 check_running()
203 {
204         [ -r "$CHDIR/.pid" ] || return
205         PID=$(< "$CHDIR/.pid")
206         if [ -d /proc/$PID ]; then
207                 die 10 "Another process ($PID) already running in $CHNAME"
208         fi
209 }
210
211 for D in installed buildlogs $CACHEDIR; do
212         if [ ! -d "$D" ]; then
213                 info "mkdir $D"
214                 su $USER -c "mkdir -p $D" || die 13 "Cannot create work directories"
215         fi
216 done
217
218 ignore \
219         vserver-packages \
220         upstart\* \
221         compat-\* \
222         systemd-init \
223         kmod \
224         xorg-driver-video-fglrx\* xorg-driver-video-nvidia\* xorg-xserver-xgl-libGL \
225         xorg-data-xbitmaps \
226         compat-gcc\* \
227         libpng1\* \
228         libjpeg-turbo \
229         freetype1-devel-* \
230         anacron fcron hc-cron \
231         masqmail msmtp-sendmail omta postfix sendmail ssmtp nail-mail nullmailer \
232         ghostscript-esp \
233         \*-multilib-\* \
234         gnome-speech-driver-festival gnome-speech-driver-speech-dispatcher
235
236
237 rebuilddb()
238 {
239         $NOREBUILDDB || rpm --root=$CHDIR --rebuilddb
240 }
241
242 poldek()
243 {
244         $NODEBUG || set -x
245         rebuilddb
246         /usr/bin/poldek $SRC -s "$RPMS_FROM" -r "$CHDIR" "--cachedir=$CACHEDIR" --conf=$PWD/poldekconf/poldek.conf "$@"
247 }
248
249
250 build_umount()
251 {
252         for DIR in $CHHOME/rpm $CHHOME dev proc sys; do
253                 [ -d $CHDIR/$DIR ] && umount $CHDIR/$DIR
254         done
255 }
256
257 build_remove_root()
258 {
259         $NODEBUG || set -x
260         if $FORCE_UMOUNT; then
261                 # safety checks.
262                 [ "$CHDIR" ] || exit 1
263                 [ -d "$CHDIR" ] || exit 1
264                 rm -rf $CHDIR/*
265                 umount -l $CHDIR
266         else
267                 umount $CHDIR
268         fi
269         rmdir $CHDIR
270 }
271
272 clean()
273 {
274         info "Cleaning $CHNAME"
275         title "cleaning chroot"
276         build_umount
277         build_remove_root
278 }
279
280 build_prepare_root()
281 {
282         title "preparing chroot"
283         set -e
284         $NODEBUG || set -x
285         mkdir $CHDIR
286         mount -t tmpfs -o size=$CHROOTSIZE,relatime /dev/null $CHDIR
287         echo $$ > $CHDIR/.pid
288
289         rpmversion=$(rpm -E '%(v=%{_rpmversion}; IFS=.; set -- $v; echo $1)')
290         rpmversion=${rpmversion:-4}
291
292         if [ "$rpmversion" -ge 5 ]; then
293                 rpm --root=$CHDIR -qa
294         else
295                 rpm --root=$CHDIR --initdb
296         fi
297         poldek --up || :
298         poldek -O "ignore=$IGNORE" -u rpm-build util-linux
299         echo Poldek exit: $?
300
301         for DIR in dev proc sys; do
302                 # We need to create these directories manually, because they are marked
303                 # as netsharedpath in cleanbuild poldek.conf
304                 mkdir $CHDIR/$DIR
305                 mount -o bind /$DIR $CHDIR/$DIR
306         done
307
308         chroot $CHDIR useradd -m $USER -u$(id $USER -u)
309
310         # replicate files which already belong to $USER
311         # so they will have correct owner and permissions
312         cp -a $CHDIR/$CHHOME/{tmp,rpm}
313         cp -a $CHDIR/$CHHOME/tmp $CHDIR$BUILDDIR
314
315         cp -a $CHDIR/$CHHOME/{.bashrc,.rpmmacros}
316         cat <<-EOM > $CHDIR/$CHHOME/.rpmmacros
317         %_builddir              $BUILDDIR
318         %buildroot              %{_builddir}/%{name}-%{version}-root-%(id -u -n)
319         %_rpmdirname    cleanRPMS
320         %_rpmdir                %{expand:%%global _rpmdir %([ -d %{_topdir}/../%{_rpmdirname} ] && (cd %{_topdir}/../%{_rpmdirname}; pwd) || echo %{_topdir}/%{_rpmdirname})}%_rpmdir
321         %distribution   CleanPLD
322         %_binary_payload        w1.gzdio
323 EOM
324         [ -z "$RPMMACROS" ] || echo "$RPMMACROS" >> $CHDIR/$CHHOME/.rpmmacros
325
326         cp -a $CHDIR/$CHHOME/{.bashrc,.builderrc}
327         cat <<-'EORC' > $CHDIR/$CHHOME/.builderrc
328         TITLECHANGE=no
329 EORC
330         [ -z "$BUILDERRC" ] || echo "$BUILDERRC" >> $CHDIR/$CHHOME/.builderrc
331
332         set +e
333 }
334
335 build_mount_home()
336 {
337         $NODEBUG || set -x
338         mount -o bind $HOME/rpm $CHDIR/$CHHOME/rpm
339 }
340
341
342 print_installed()
343 {
344         echo=$1
345         if [ -r installed/$build_pkg ]; then
346                 $echo "$(cat installed/$build_pkg | awk '{print $1}' | sort -u \
347                         | awk '{br=br ", " $1} END{gsub(/^, /, "- BR: ", br ); print br}')"
348                 cat installed/$build_pkg
349         fi
350 }
351
352 addlist()
353 {
354         LIST="$1"
355
356         print_installed info
357
358         return
359         echo "*** $build_pkg $(date --rfc-3339=seconds) ***" >> $LIST
360         print_installed echo >> $LIST
361 }
362
363 builddie()
364 {
365         LIST="$1"; shift
366         CODE="$1"; shift
367         MSG="$*"
368
369         rm -f $CHDIR/.pid
370
371         $CLEANAFTER && clean
372         title "failed !"
373
374         addlist "ERROR_$LIST"
375         die $CODE "$MSG"
376 }
377
378 LAST_INSTALL=""
379 poldek_install()
380 {
381         I="$1";
382         # Nothing to install
383         [ -n "$I" ] || return 1
384         # Installing same packets second time
385         [ "$LAST_INSTALL" != "$I" ] || return 1
386         LAST_INSTALL="$I"
387
388         info "Installing" $I
389         poldek -O "ignore=$IGNORE" -u $I | tee $$.poldek_install
390         ret=
391         if grep -q "Preparing...                ##################################################" $$.poldek_install \
392                         && ! grep -q "file .* from install of .* conflicts with file from package" $$.poldek_install
393                 then
394                 info "Poldek:" $I "installed"
395                 ret=0
396         elif grep -q "Nothing to do" $$.poldek_install; then
397                 warn "Poldek:" $I "installed already"
398                 ret=1
399         fi
400         rm $$.poldek_install
401         [ -n "$ret" ] && return $ret
402
403         # try harder
404         poldek -u $I && return 0
405         poldek -u $I && return 0
406         warn "Poldek:" "Could not install" $I
407         return 1
408 }
409
410 maybe_call()
411 {
412         local cond="$1"; shift
413         local func="$1"; shift
414
415         [ $cond = "false" ] && return
416         $func "$@"
417         [ $cond = "exit_after" ] && exit
418 }
419
420 fetch()
421 {
422         info "Fetching $build_pkg"
423         title "fetch"
424         $NODEBUG || set -x
425         su $USER -c "$HOME/rpm/packages/builder -g $build_pkg $builder_options" \
426                 || die 11 "Fetch failed"
427 }
428
429 create()
430 {
431         $NODEBUG || set -x
432         su $USER -c "poldek -s $RPMS_FROM --mkidx"
433
434         if [ ! -d $CHDIR ]; then
435                 info "Preparing $CHNAME"
436                 build_prepare_root
437                 build_mount_home
438         fi
439 }
440
441
442 info "Configured Poldek sources"
443 poldek -l
444
445 maybe_call $FETCH fetch
446
447 check_running
448
449 maybe_call $CLEAN clean
450
451 maybe_call $CREATE create
452
453 echo $$ > $CHDIR/.pid
454
455 maybe_call $INSTALL poldek_install "$*"
456
457 $BUILD || exit
458
459 if [ -p /tmp/fixfreq ]; then
460         echo $$ > /tmp/fixfreq
461 fi
462
463 while true; do
464         info "Building $build_pkg in $CHNAME"
465         rebuilddb
466         find $CHDIR/usr/lib{,64} -name "*.la" -print0 | \
467                 xargs -0 -r sed -i -e "s@dependency_libs=.*@dependency_libs=' '@"
468         buildlog="buildlogs/$build_pkg"
469         if [ -r $buildlog ]; then
470                 i=1
471                 while [ -r $buildlog.$i ]; do
472                         i=$((i+1))
473                 done
474                 info "moving $buildlog to $buildlog.$i"
475                 mv $buildlog $buildlog.$i
476         fi
477         ./findunusedbr -c $CHDIR $HOME/rpm/packages/$build_pkg/$build_pkg.spec
478         title "building"
479         ./teeboth $buildlog chroot $CHDIR su $USER -c "$CHHOME/rpm/packages/builder -nn -bb $build_pkg $builder_options"
480         ECODE=$?
481
482         if grep -q "error: Failed build dependencies:" $buildlog; then
483                 SEARCH=$(cat $buildlog | awk '/^Error:/ { p = 0 }; { if ( p ) { f="p"; if ( $1 ~ /^\// ) f="f"; printf "search -%c %s; ", f, $1; } }; /error: Failed build dependencies:/ { p = 1 }')
484                 INSTALL=$(poldek -O "ignore=$IGNORE" --shcmd="$SEARCH" | awk '{ if ( p ) { print; p = 0; } } / package\(s\) found:$/ { p = 1 }' | sed 's/^\(.*\)-.*-.*$/\1/' | sort -u)
485
486                 if poldek_install "$INSTALL"; then
487                         info "Deps installed"
488                         continue
489                 else
490                         addlist ERROR_BRINSTALL
491                         die 4 "Cannot install BRs"
492                 fi
493         fi
494
495         ./findbr $CHDIR/$BUILDDIR $buildlog > $$.installed
496         installed_something=false
497         while read pkg msg; do
498                 if poldek_install $pkg; then
499                         info "findbr:" $pkg "installed"
500                         echo "$pkg $msg" >> installed/$build_pkg
501                         ./addbr $build_pkg "$pkg" "$msg"
502                         installed_something=true
503                 else
504                         warn "findbr:" $pkg "not installed"
505                 fi
506         done < $$.installed
507         rm -f $$.installed
508         $installed_something && continue
509
510         if [ $ECODE -eq 0 ]; then
511                 $CLEANAFTER && clean
512                 addlist BUILT_OK
513                 ./findunusedbr $CHDIR $HOME/rpm/packages/$build_pkg/$build_pkg.spec
514                 info "$build_pkg built OK !"
515                 title "OK !"
516                 exit 0
517         else
518                 builddie UNKNOWN 1 "Got error but dunno what to do !"
519         fi
520 done
521
522
523 # vim: ts=4 sw=4 filetype=sh
This page took 0.081255 seconds and 4 git commands to generate.