projects/aports·blob v2.1 · refs

1090 lines · 24.8 KiB

1#!/bin/sh
2
3# script to build apk packages (light version of makepkg)
4# Copyright (c) 2008 Natanael Copa <[email protected]>
5#
6# Distributed under GPL-2
7#
8# Depends on: busybox utilities, fakeroot,
9#
10
11abuild_ver=@VERSION@
12sysconfdir=@sysconfdir@
13apkcache=@apkcache@
14datadir=@datadir@
15
16program=${0##*/}
17abuild_path=$(readlink -f $0)
18
19# defaults
20BUILD_BASE="build-base"
21SUDO=${SUDO:-"sudo"}
22FAKEROOT=${FAKEROOT:-"fakeroot"}
23
24# read config
25ABUILD_CONF=${ABUILD_CONF:-"$sysconfdir/abuild.conf"}
26[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"
27
28
29#colors
30if [ -n "$USE_COLORS" ]; then
31 NORMAL="\033[1;0m"
32 STRONG="\033[1;1m"
33 RED="\033[1;31m"
34 GREEN="\033[1;32m"
35 YELLOW="\033[1;33m"
36 BLUE="\033[1;34m"
37fi
38
39
40# functions
41msg() {
42 local prompt="$GREEN>>>${NORMAL}"
43 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
44 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
45 [ -z "$quiet" ] && printf "${prompt} ${name}${fake}: $@\n" >&2
46}
47
48warning() {
49 local prompt="${YELLOW}>>> WARNING:${NORMAL}"
50 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
51 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
52 printf "${prompt} ${name}${fake}: $@\n" >&2
53}
54
55error() {
56 local prompt="${RED}>>> ERROR:${NORMAL}"
57 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
58 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
59 printf "${prompt} ${name}${fake}: $@\n" >&2
60}
61
62
63set_xterm_title() {
64 if [ "$TERM" = xterm ]; then
65 printf "\033]0;$1\007" >&2
66 fi
67}
68
69cleanup() {
70 set_xterm_title ""
71 if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then
72 $SUDO apk del $uninstall_after
73 fi
74}
75
76die() {
77 error "$@"
78 cleanup
79 exit 1
80}
81
82# check if apkbuild is basicly sane
83sanitycheck() {
84 local i
85 msg "Checking sanity of $APKBUILD..."
86 [ -z "$pkgname" ] && die "Missing pkgname in APKBUILD"
87 [ -z "${pkgname##* *}" ] && die "pkgname contains spaces"
88 [ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
89 if [ "$pkgver" != "volatile" ] && [ -z "$nodeps" ]; then
90 apk version --check -q "$pkgver" ||\
91 die "$pkgver is not a valid version"
92 fi
93 [ -z "$pkgrel" ] && warning "Missing pkgrel in APKBUILD. Using pkgrel=0"
94 [ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD"
95 [ -z "$url" ] && die "Missing url in APKBUILD"
96 [ -z "$license" ] && die "Missing license in APKBULID"
97
98 for i in $install; do
99 [ -e "$startdir/$i" ] || die "install script $startdir/$i is missing"
100 done
101
102 [ -n "${triggers%%:*}" ] && [ ! -e "$startdir"/${triggers%%:*} ] \
103 && die "trigger script $startdir/${triggers%%:*} is missing"
104
105 if [ -n "$source" ]; then
106 for i in $source; do
107 if install_has "$i"; then
108 warning "You should not have \$install in source"
109 continue
110 fi
111 md5sums_has ${i##*/} || die "${i##*/} is missing in md5sums"
112 case "$i" in
113 https://*) makedepends_has wget || die "wget must be in makedepends when source has https://" ;;
114 esac
115 done
116 fi
117
118 if [ -n "$md5sums" ]; then
119 for i in $(echo "$md5sums" | awk '{ print $2 }'); do
120 source_has $i || die "$i exists in md5sums but is missing in source"
121 done
122 fi
123
124 # common spelling errors
125 [ -n "$depend" ] && die "APKBUILD contains 'depend'. It should be depends"
126 [ -n "$makedepend" ] && die "APKBUILD contains 'makedepend'. It should be makedepends"
127
128 grep '^# Maintainer:' $APKBUILD >/dev/null || warning "No maintainer"
129
130 makedepends_has 'g++' && warning "g++ should not be in makedepends"
131 return 0
132}
133
134md5check() {
135 local dummy f
136 if [ -z "$source" ]; then
137 return 0
138 fi
139 if [ -z "$md5sums" ]; then
140 die "Use 'abuild checksum' to generate/update the checksum(s)"
141 fi
142 if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
143 die "Number of md5sums does not correspond to number of sources"
144 fi
145 fetch || return 1
146 msg "Checking md5sums..."
147 cd "$srcdir" && echo "$md5sums" | md5sum -c
148}
149
150uri_fetch() {
151 local uri="$1"
152 local d="${s##*/}" # $(basename $s)
153 local opts
154 [ -n "$quiet" ] && opts="-q"
155 [ -f "$SRCDEST/$d" ] && return 0
156
157
158 # we need GNU wget for this
159 case "$uri" in
160 https://*) opts="--no-check-certificate";;
161 esac
162
163 mkdir -p "$SRCDEST"
164 if [ -f "$SRCDEST/$d.part" ]; then
165 msg "Partial download found. Trying to resume"
166 opts="$opts -c"
167 fi
168 msg "Fetching $uri"
169 wget $opts -O "$SRCDEST/$d.part" "$uri" \
170 && mv "$SRCDEST/$d.part" "$SRCDEST/$d"
171}
172
173is_remote() {
174 case "$1" in
175 http://*|ftp://*|https://*)
176 return 0;;
177 esac
178 return 1
179}
180
181default_fetch() {
182 local s
183 mkdir -p "$srcdir"
184 for s in $source; do
185 if is_remote "$s"; then
186 uri_fetch "$s" || return 1
187 ln -sf "$SRCDEST/${s##*/}" "$srcdir"/
188 else
189 ln -sf "$startdir/$s" "$srcdir/"
190 fi
191 done
192}
193
194fetch() {
195 default_fetch
196}
197
198# unpack the sources
199default_unpack() {
200 local u
201 md5check || return 1
202 mkdir -p "$srcdir"
203 for u in $source; do
204 local s="$SRCDEST/${u##*/}" # $(basename $s)
205 case "$s" in
206 *.tar.gz|*.tgz)
207 msg "Unpacking $s..."
208 tar -C "$srcdir" -zxf "$s" || return 1;;
209 *.tar.bz2)
210 msg "Unpacking $s..."
211 tar -C "$srcdir" -jxf "$s" || return 1;;
212 *.tar.lzma)
213 msg "Unpacking $s..."
214 unlzma -c "$s" | tar -C "$srcdir" -x \
215 || return 1;;
216 *.zip)
217 msg "Unpacking $s..."
218 unzip "$s" -d "$srcdir" || return 1;;
219 esac
220 done
221}
222
223unpack() {
224 default_unpack
225}
226
227# cleanup source and package dir
228clean() {
229 msg "Cleaning temporary build dirs..."
230 rm -rf "$srcdir"
231 rm -rf "$pkgbasedir"
232}
233
234# cleanup fetched sources
235cleancache() {
236 local s
237 for s in $source; do
238 if is_remote "$s"; then
239 msg "Cleaning downloaded ${s##*/}..."
240 rm -f "$SRCDEST/${s##*/}"
241 fi
242 done
243}
244
245cleanpkg() {
246 local i
247 getpkgver || return 1
248 msg "Cleaning built packages..."
249 for i in $pkgname $subpackages; do
250 local p="${i%:*}-$pkgver-r$pkgrel"
251 rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz" \
252 "$apkcache"/$p.apk
253 done
254 # remove given packages from index
255}
256
257# clean all packages except current
258cleanoldpkg() {
259 local i j
260 getpkgver || return 1
261 msg "Cleaning all packages except $pkgver-r$pkgrel..."
262 for i in $pkgname $subpackages; do
263 for j in "$PKGDEST"/${i%:*}-[0-9]*.apk; do
264 [ "$j" != "$PKGDEST/${i%:*}-$pkgver-r$pkgrel.apk" ] \
265 && rm -f "$j"
266 done
267 done
268 return 0
269}
270
271mkusers() {
272 local i
273 for i in $pkgusers; do
274 if ! getent passwd $i >/dev/null; then
275 msg "Creating user $i"
276 $SUDO adduser -D -H $i || return 1
277 fi
278 done
279 for i in $pkggroups; do
280 if ! getent group $i >/dev/null; then
281 msg "Creating group $i"
282 $SUDO addgroup $i || return 1
283 fi
284 done
285}
286
287
288runpart() {
289 local part=$1
290 [ -n "$DEBUG" ] && msg "$part"
291 $part || die "$part failed"
292}
293
294# override those in your build script
295getpkgver() {
296 # this func is supposed to be overridden by volatile packages
297 if [ "$pkgver" = "volatile" ]; then
298 error "Please provide a getpkgver() function in your APKBUILD"
299 return 1
300 fi
301}
302
303prepare() {
304 :
305}
306
307build() {
308 :
309}
310
311get_split_func() {
312 # get the 'func' from "sub-pkg:func"
313 local func=${1##*:}
314
315 # get 'func' from "sub-pkg-func" if there was no :func
316 [ "$func" = "$1" ] && func=${func##*-}
317 echo $func
318}
319
320prepare_subpackages() {
321 if [ -z "$subpackages" ]; then
322 return 0
323 fi
324 local i
325 cd "$startdir"
326 for i in $subpackages; do
327 local func=$(get_split_func $i)
328 # call abuild recursively, setting subpkg{dir,name}
329 msg "Running split function $func..."
330 subpkgdir="$pkgbasedir/${i%:*}" subpkgname="${i%:*}" \
331 $0 $func prepare_package || return 1
332 done
333}
334
335prepare_metafiles() {
336 getpkgver || return 1
337 local name=${subpkgname:-$pkgname}
338 [ -z "${name##* *}" ] && die "package name contains spaces"
339 local dir=${subpkgdir:-$pkgdir}
340 local pkg="$name-$pkgver-r$pkgrel.apk"
341 local pkginfo="$controldir"/.PKGINFO
342 local sub
343
344 [ ! -d "$dir" ] && die "Missing $dir"
345 cd "$dir"
346 mkdir -p "$controldir"
347 local builddate=$(date -u "+%s")
348 local size=$(du -sk | awk '{print $1 * 1024}')
349
350 echo "# Generated by $(basename $0) $abuild_ver" >"$pkginfo"
351 if [ -n "$FAKEROOTKEY" ]; then
352 echo "# using $($FAKEROOT -v)" >> "$pkginfo"
353 fi
354 echo "# $(date -u)" >> "$pkginfo"
355 cat >> "$pkginfo" <<EOF
356pkgname = $name
357pkgver = $pkgver-r$pkgrel
358pkgdesc = $pkgdesc
359url = $url
360builddate = $builddate
361packager = ${PACKAGER:-"Unknown"}
362size = $size
363EOF
364 local i deps
365 deps="$depends"
366 if [ "$pkgname" != "busybox" ] && ! depends_has busbox; then
367 for i in $install ${triggers%%:*}; do
368 if head -n 1 "$startdir/$i" | grep '^#!/bin/sh' >/dev/null ; then
369 msg "Script found. busybox added as a dependency for $pkg"
370 deps="$deps busybox"
371 break
372 fi
373 done
374 fi
375
376 for i in $license; do
377 echo "license = $i" >> "$pkginfo"
378 done
379 for i in $replaces; do
380 echo "replaces = $i" >> "$pkginfo"
381 done
382 for i in $deps; do
383 echo "depend = $i" >> "$pkginfo"
384 done
385 for i in $conflicts; do
386 echo "conflict = $i" >> "$pkginfo"
387 done
388 for i in $provides; do
389 echo "provides = $i" >> "$pkginfo"
390 done
391 for i in $backup; do
392 echo "backup = $i" >> "$pkginfo"
393 done
394 if [ -n "$triggers" ]; then
395 echo "triggers = ${triggers#*:}" >> "$pkginfo"
396 fi
397
398 local metafiles=".PKGINFO"
399 for i in $install ${triggers%%:*}; do
400 script=${i#$name}
401 case "$script" in
402 .pre-install|.post-install|.pre-upgrade|.post-upgrade|.pre-deinstall|.post-deinstall|.trigger)
403 msg "Adding $script"
404 ;;
405 *) error "$script: Invalid install/trigger script"
406 return 1
407 ;;
408 esac
409 cp "$startdir/$i" "$controldir/$script" || return 1
410 chmod +x "$controldir/$script"
411 metafiles="$metafiles $script"
412 done
413 echo $metafiles | tr ' ' '\n' > "$controldir"/.metafiles
414}
415
416prepare_tracedeps() {
417 local dir=${subpkgdir:-$pkgdir}
418 options_has "!tracedeps" && return 0
419 find -name '*.so' -o -name '*.so.[0-9]*' | sed 's:.*/::' \
420 >"$controldir"/.provides-so
421 scanelf -Rn "$dir" | awk -F "\ " '$1 == "ET_DYN" || $1 == "ET_EXEC" {print $2}' \
422 | sed 's:,:\n:g' | sort | uniq \
423 | while read i; do
424 # only add files that are not self provided
425 grep "^$i$" "$controldir"/.provides-so >/dev/null \
426 || echo $i >> "$controldir"/.needs-so
427 done
428}
429
430prepare_package() {
431 msg "Preparing ${subpkgname:+sub}package ${subpkgname:-$pkgname}..."
432 stripbin
433 prepare_metafiles && prepare_tracedeps
434}
435
436pkginfo_val() {
437 local key="$1"
438 local file="$2"
439 awk -F ' = ' "\$1 == \"$key\" {print \$2}" "$file"
440}
441
442trace_apk_deps() {
443 local name="$1"
444 local dir="$2"
445 local i j found autodeps=
446 msg "Tracing dependencies for $name..."
447 # add pkgconfig if usr/lib/pkgconfig is found
448 if [ -d "$pkgbasedir"/$name/usr/lib/pkgconfig ] \
449 && ! grep -q '^depend = pkgconfig' "$dir"/.PKGINFO; then
450 msg "Added pkgconfig as dependency"
451 echo "depend = pkgconfig" >> "$dir"/.PKGINFO
452 fi
453 for i in $(cat "$dir"/.needs-so 2>/dev/null); do
454 found=
455 # first check if its provide by same apkbuild
456 for j in "$dir"/../.control.*/.provides-so; do
457 grep -w "$i" "$j" >/dev/null || continue
458 found=${j%/.provides-so}
459 found=${found##*/.control.}
460 break
461 done
462 # check apk db if not provided by a subpackage
463 if [ -z "$found" ]; then
464 found=$(apk info -q -W /lib/$i /usr/lib/$i)
465 fi
466 if [ -z "$found" ]; then
467 error "Could not find dependency for $i"
468 return 1
469 fi
470 if grep -w "^depend = ${found}$" "$dir"/.PKGINFO >/dev/null ; then
471 warning "You can remove '$found' from depends"
472 continue
473 fi
474 list_has "$found" $autodeps || autodeps="$autodeps $found"
475 msg "Added '$found' as dependency as it has $i"
476 done
477 [ -z "$autodeps" ] && return 0
478 echo "# automatically detected:" >> "$dir"/.PKGINFO
479 for i in $autodeps; do
480 echo "depend = $i" >> "$dir"/.PKGINFO
481 done
482}
483
484create_apks() {
485 local file
486 getpkgver || return 1
487 for file in "$pkgbasedir"/.control.*/.PKGINFO; do
488 local dir="${file%/.PKGINFO}"
489 local name=$(pkginfo_val pkgname $file)
490 local ver=$(pkginfo_val pkgver $file)
491 local apk=$name-$ver.apk
492 local datadir="$pkgbasedir"/$name
493
494 trace_apk_deps "$name" "$dir" || return 1
495 msg "Creating $apk..."
496 (
497 cd "$datadir"
498 # data.tar.gz
499 set -- *
500 if [ "$1" = '*' ]; then
501 touch .dummy
502 set -- .dummy
503 fi
504 tar -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz
505
506 # append the hash for data.tar.gz
507 local sha256=$(sha256sum "$dir"/data.tar.gz | cut -f1 -d' ')
508 echo "datahash = $sha256" >> "$dir"/.PKGINFO
509
510 # control.tar.gz
511 cd "$dir"
512 tar -c $(cat "$dir"/.metafiles) | abuild-tar --cut \
513 | gzip -9 > control.tar.gz
514 abuild-sign -q control.tar.gz || exit 1
515
516 # create the final apk
517 cat control.tar.gz data.tar.gz > "$PKGDEST"/$apk
518 )
519 done
520}
521
522apkcache() {
523 if ! apk_up2date || [ -n "$force" ]; then
524 sanitycheck && builddeps && clean && fetch && unpack \
525 && prepare && mkusers && rootpkg || return 1
526 fi
527
528 local apk
529 mkdir -p "$apkcache" || return 1
530 cd "$apkcache"
531
532 # remove broken links
533 for apk in *.apk; do
534 if [ -L "$apk" ] && [ ! -f "$apk" ]; then
535 rm -f "$apk"
536 fi
537 done
538
539 # create links for this package
540 for apk in $(listpkg); do
541 ln -sf "$PKGDEST"/$apk "$apkcache"/$apk
542 done
543
544 msg "Updating the cached abuild repository index..."
545 local sign=".SIGN.RSA.${SIGN_PUBLIC_KEY##*/}"
546 local oldindex=
547 if [ -f APKINDEX.tar.gz ]; then
548 oldindex="--index APKINDEX.tar.gz"
549 fi
550 apk index $oldindex --output APKINDEX.tar.gz.unsigned \
551 --description "$repo $(cd $startdir && git describe)" \
552 *.apk || exit 1
553 msg "Signing the index..."
554 abuild-sign -q APKINDEX.tar.gz.unsigned || exit 1
555 mv APKINDEX.tar.gz.unsigned APKINDEX.tar.gz
556 chmod 644 APKINDEX.tar.gz
557}
558
559# predefined splitfunc doc
560default_doc() {
561 depends="$depends_doc"
562 install="$install_doc"
563 triggers="$triggers_doc"
564 local i
565 for i in doc man info html sgml licenses gtk-doc; do
566 if [ -d "$pkgdir/usr/share/$i" ]; then
567 mkdir -p "$subpkgdir/usr/share"
568 mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/"
569 fi
570 done
571
572 rm -f "$subpkgdir/usr/share/info/dir"
573
574# # compress info and man pages
575# find "$subpkgdir/usr/share" \( -name '*.info' -o -name '*.info-[1-9]' \
576# -o -name '*.[1-9]' \) -exec gzip {} \;
577
578 # remove if empty, ignore error (not empty)
579 rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null
580
581# [ -d "$subpkgdir/usr/share/man" ] && depends="man"
582 return 0
583}
584
585doc() {
586 default_doc
587}
588
589# predefined splitfunc mod
590default_mod() {
591 depends="$kernel $depends_mod"
592 install="$install_mod"
593 for i in firmware modules; do
594 if [ -d "$pkgdir/lib/$i" ]; then
595 rm -rf "$subpkgdir/lib"
596 mkdir -p "$subpkgdir/lib"
597 mv "$pkgdir/lib/$i" "$subpkgdir/lib"
598 fi
599 done
600}
601
602mod() {
603 default_mod
604}
605
606# predefined splitfunc dev
607default_dev() {
608 local i
609 depends="$pkgname $depends_dev"
610 install="$install_dev"
611 triggers="$triggers_dev"
612 for i in $origsubpackages; do
613 [ "${i%:*}" = "$subpkgname" ] || depends="$depends ${i%:*}"
614 done
615
616 cd "$pkgdir" || return 0
617 for i in usr/include usr/lib/pkgconfig usr/share/aclocal\
618 usr/share/gettext usr/bin/*-config \
619 $(find -name include -type d) \
620 $(find usr/ -name '*.[acho]' -o -name '*.la' \
621 2>/dev/null); do
622 if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
623 d="$subpkgdir/${i%/*}" # dirname $i
624 mkdir -p "$d"
625 mv "$pkgdir/$i" "$d"
626 rmdir "$pkgdir/${i%/*}" 2>/dev/null
627 fi
628 done
629 return 0
630}
631
632dev() {
633 default_dev
634}
635
636is_function() {
637 type "$1" 2>&1 | head -n 1 | egrep -q "is a (shell )?function"
638}
639
640# build and package in fakeroot
641rootpkg() {
642 local do_build=build
643 cd "$startdir"
644 if is_function package; then
645 build || return 1
646 do_build=package
647 fi
648 cd "$startdir"
649 [ -n "$FAKEROOT" ] && msg "Entering fakeroot..."
650 $FAKEROOT "$abuild_path" $do_build \
651 prepare_subpackages \
652 prepare_package \
653 create_apks
654}
655
656srcpkg() {
657 getpkgver || return 1
658 local p="$pkgname-$pkgver-$pkgrel"
659 local prefix="${startdir##*/}"
660 local i files="$prefix/APKBUILD"
661 for i in $source; do
662 files="$files $prefix/${i##*/}"
663 done
664 mkdir -p "$PKGDEST"
665 msg "Creating source package $p.src.tar.gz..."
666 (cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files)
667}
668
669# check if package is up to date
670apk_up2date() {
671 getpkgver || return 1
672 local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk"
673 local i s
674 cd "$startdir"
675 for i in $pkgname $subpackages; do
676 [ -f "$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" ] || return 1
677 done
678 [ -n "$keep" ] && return 0
679
680 for i in $source APKBUILD; do
681 local s
682 if is_remote "$i"; then
683 s="$SRCDEST/${i##*/}" # $(basename $i)
684 else
685 s="$startdir/${i##*/}"
686 fi
687 if [ "$s" -nt "$pkg" ]; then
688 return 1
689 fi
690 done
691 return 0
692}
693
694cache_up2date() {
695 local i apk
696 getpkgver || return 1
697 for i in $pkgname $subpackages; do
698 apk="${i%:*}-$pkgver-r$pkgrel.apk"
699 [ "$apkcache"/APKINDEX.tar.gz -nt "$apkcache"/$apk ] || return 1
700 done
701 return 0
702}
703
704up2date() {
705 apk_up2date && cache_up2date
706}
707
708# source all APKBUILDs and output:
709# 1) origin of package
710# 2) all dependencies
711# the output is i in a format easy parseable for awk
712depparse_aports() {
713 # lets run this in a subshell since we source all APKBUILD here
714 (
715 aportsdir=$(realpath ${APKBUILD%/APKBUILD}/../..)
716 for i in $aportsdir/*/*/APKBUILD; do
717 pkgname=
718 subpackages=
719 depends=
720 makedepends=
721 . $i
722 dir=${i%/APKBUILD}
723 deps=
724 # filter out conflicts from deps and version info
725 for j in $depends $makedepends; do
726 case "$j" in
727 !*) continue;;
728 esac
729 deps="$deps ${j%[<>=]*}"
730 done
731 for j in $pkgname $subpackages; do
732 echo "o ${j%%:*} $dir"
733 set -- $deps
734 echo -n "d ${j%%:*} $1"
735 shift
736 while [ $# -gt 0 ]; do
737 echo -n ",$1"
738 shift
739 done
740 echo
741 done
742 done
743 )
744}
745
746deptrace() {
747 local deps= i=
748 # strip versions from deps
749 for i in "$@"; do
750 deps="$deps ${i%[<>=]*}"
751 done
752 [ -z "$deps" ] && return 0
753 ( depparse_aports
754 if [ -z "$upgrade" ]; then
755 # list installed pkgs and prefix with 'i '
756 apk info -q | sort | sed 's/^/i /'
757 fi
758 ) | awk -v pkgs="$deps" '
759
760 function depgraph(pkg, a, i) {
761 if (visited[pkg])
762 return 0;
763 visited[pkg] = 1;
764 split(deps[pkg], a, ",");
765 for (i in a)
766 depgraph(a[i]);
767 print pkg ":" origin[pkg];
768
769 }
770
771 $1 == "i" { visited[$2] = 1 }
772 $1 == "o" { origin[$2] = $3 }
773 $1 == "d" { deps[$2] = $3 }
774 END {
775 split(pkgs, pkgarray);
776 for (i in pkgarray)
777 depgraph(pkgarray[i]);
778 }
779 '
780}
781
782# build and install dependencies
783builddeps() {
784 local deps= alldeps= pkg= i= dir= ver= missing= installed_deps=
785 local filtered_deps=
786 [ -n "$nodeps" ] && return 0
787 msg "Analyzing dependencies..."
788 deps="$BUILD_BASE $makedepends"
789
790 # add depends unless it is a subpackage
791 for i in $depends; do
792 subpackages_has ${i%[<>=]*} || deps="$deps $i"
793 done
794
795 installed_deps=$(apk info -e $deps)
796 # find which deps are missing
797 for i in $deps; do
798 if [ "${i#\!}" != "$i" ]; then
799 list_has ${i#\!} $installed_deps \
800 && die "Conflicting package ${i#\!} is installed."
801 elif ! deplist_has $i $installed_deps; then
802 if [ -z "$install_deps" ] && [ -z "$recursive" ]; then
803 die "Missing dependency $i. Use -r to autoinstall or -R to build"
804 fi
805 missing="$missing $i"
806 fi
807 done
808
809 [ -z "$missing" ] && [ -z "$install_deps" ] && [ -z "$recursive" ] \
810 && return 0
811
812 uninstall_after=".makedepends-$pkgname $uninstall_after"
813 if [ -n "$install_deps" ] && [ -z "$recursive" ]; then
814 $SUDO apk add --repository "$apkcache" \
815 --virtual .makedepends-$pkgname $deps \
816 && return 0
817 fi
818
819 [ -z "$recursive" ] && return 1
820
821 # find dependencies that are installed but missing in repo.
822 for i in $deps; do
823 local m=$(apk search --repository "$apkcache" ${i%[<>=]*})
824 if [ -z "$m" ]; then
825 missing="$missing $i"
826 fi
827 done
828
829 for i in $(deptrace $missing); do
830 # i = pkg:dir
831 local dir=${i#*:}
832 local pkg=${i%:*}
833 msg "Entering $dir"
834 cd "$dir" && $0 -k -r apkcache || return 1
835 done
836 $SUDO apk add -u --repository "$apkcache" \
837 --virtual .makedepends-$pkgname $deps
838}
839
840# replace the md5sums in the APKBUILD
841checksum() {
842 local s files
843 [ -z "$source" ] && return 0
844 fetch
845 msg "Updating the md5sums in APKBUILD..."
846 for s in $source; do
847 files="$files ${s##*/}"
848 done
849 md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
850 sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
851 echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
852}
853
854stripbin() {
855 local bin
856 options_has "!strip" && return 0
857 cd "${subpkgdir:-$pkgdir}" || return 1
858 msg "Stripping binaries"
859 scanelf --recursive --nobanner --etype "ET_DYN,ET_EXEC" . \
860 | sed -e 's:^ET_DYN ::' -e 's:^ET_EXEC ::' \
861 | xargs -r strip
862}
863
864# simply list target apks
865listpkg() {
866 local i
867 getpkgver || return 1
868 for i in $pkgname $subpackages; do
869 echo "${i%:*}-$pkgver-r$pkgrel.apk"
870 done
871}
872
873source_has() {
874 local i
875 for i in $source; do
876 [ "$1" = "${i##*/}" ] && return 0
877 done
878 return 1
879}
880
881subpackages_has() {
882 local i
883 for i in $subpackages; do
884 [ "$1" = "${i%:*}" ] && return 0
885 done
886 return 1
887}
888
889list_has() {
890 local needle="$1"
891 local i
892 shift
893 for i in $@; do
894 [ "$needle" = "$i" ] && return 0
895 [ "$needle" = "!$i" ] && return 1
896 done
897 return 1
898}
899
900# same as list_has but we filter version info
901deplist_has() {
902 local needle="$1"
903 local i
904 shift
905 for i in $@; do
906 i=${i%[<>=]*}
907 [ "$needle" = "$i" ] && return 0
908 [ "$needle" = "!$i" ] && return 1
909 done
910 return 1
911}
912
913options_has() {
914 list_has "$1" $options
915}
916
917depends_has() {
918 deplist_has "$1" $depends
919}
920
921makedepends_has() {
922 deplist_has "$1" $makedepends
923}
924
925md5sums_has() {
926 list_has "$1" $md5sums
927}
928
929install_has() {
930 list_has "$1" $install
931}
932
933# install package after build
934post_add() {
935 getpkgver || return 1
936 local pkgf="$PKGDEST/$1-$pkgver-r$pkgrel.apk"
937 local deps i
938 if ! subpackages_has $1 && [ "$1" != "$pkgname" ]; then
939 die "$1 is not built by this APKBUILD"
940 fi
941 # recursively install dependencies that are provided by this APKBUILD
942 deps=$(apk index "$pkgf" 2>/dev/null | awk -F: '$1=="D" { print $2 }')
943 for i in $deps; do
944 if subpackages_has $i || [ "$i" = "$pkgname" ]; then
945 post_add $i || return 1
946 fi
947 done
948 $SUDO apk add -u "$pkgf" || die "Failed to install $1"
949}
950
951installdeps() {
952 local deps i
953 sudo apk add --repository "$apkcache" --virtual .makedepends-$pkgname \
954 $makedepends
955}
956
957uninstalldeps (){
958 sudo apk del .makedepends-$pkgname
959}
960
961all() {
962 if up2date && [ -z "$force" ]; then
963 msg "Package is up to date"
964 else
965 apkcache
966 fi
967}
968
969usage() {
970 echo "$program $abuild_ver"
971 echo "usage: $program [options] [-i PKG] [-P REPODEST] [-p PKGDEST]"
972 echo " [-s SRCDEST] [cmd] ..."
973 echo " $program [-c] -n PKGNAME[-PKGVER]"
974 echo "Options:"
975 echo " -d Disable dependency checking"
976 echo " -f Force specified cmd, even if they are already done"
977 echo " -F Force run as root"
978 echo " -h Show this help"
979 echo " -i Install PKG after successul build"
980 echo " -k Keep built packages, even if APKBUILD or sources are newer"
981 echo " -p Set package destination directory"
982 echo " -P Set PKGDEST to REPODEST/<repo>, where repo is the parents dir name"
983 echo " -q Quiet"
984 echo " -r Install missing dependencies from system repository (using sudo)"
985 echo " -R Recursively build and install missing dependencies (using sudo)"
986 echo " -s Set source package destination directory"
987 echo " -u Recursively build and upgrade all dependencies (using sudo)"
988 echo ""
989 echo "Commands:"
990 echo " checksum Generate checksum to be included in APKBUILD"
991 echo " fetch Fetch sources to \$SRCDEST and verify checksums"
992 echo " sanitycheck Basic sanity check of APKBUILD"
993 echo " md5check Check md5sums"
994 echo " unpack Unpack sources to \$srcdir"
995 echo " build Compile and install package into \$pkgdir"
996 echo " listpkg List target packages"
997 echo " package Create package in \$PKGDEST"
998 echo " rootpkg Run '$0 build package' as fakeroot"
999 echo " clean Remove temp build and install dirs"
1000 echo " cleanoldpkg Remove binary packages except current version"
1001 echo " cleanpkg Remove already built binary and source package"
1002 echo " cleancache Remove downloaded files from \$SRCDEST"
1003 echo " srcpkg Make a source package"
1004 echo " up2date Compare target and sources dates"
1005 echo " installdeps Install packages listed in makedepends and depends"
1006 echo " uninstalldeps Uninstall packages listed in makedepends and depends"
1007 echo ""
1008 exit 0
1009}
1010
1011APKBUILD="${APKBUILD:-./APKBUILD}"
1012unset force
1013unset recursive
1014while getopts "dfFhi:kinp:P:qrRs:u" opt; do
1015 case $opt in
1016 'd') nodeps=1;;
1017 'f') force=1;;
1018 'F') forceroot=1;;
1019 'h') usage;;
1020 'i') install_after="$install_after $OPTARG";;
1021 'k') keep=1;;
1022 'n') die "Use newapkbuild to create new aports";;
1023 'p') PKGDEST=$OPTARG;;
1024 'P') REPODEST=$OPTARG;;
1025 'q') quiet=1;;
1026 'r') install_deps=1;;
1027 'R') recursive=1;;
1028 's') SRCDEST=$OPTARG;;
1029 'u') upgrade=1
1030 recursive=1;;
1031 esac
1032done
1033shift $(( $OPTIND - 1 ))
1034
1035# check so we are not root
1036if [ "$(whoami)" = "root" ] && [ -z "$FAKEROOTKEY" ]; then
1037 [ -z "$forceroot" ] && die "Do not run abuild as root"
1038 SUDO=
1039 FAKEROOT=
1040fi
1041
1042# find startdir
1043[ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
1044APKBUILD=$(readlink -f "$APKBUILD")
1045
1046startdir="${APKBUILD%/*}"
1047srcdir=${srcdir:-"$startdir/src"}
1048pkgbasedir=${pkgbasedir:-"$startdir/pkg"}
1049pkgrel=0
1050repo=${startdir%/*}
1051repo=${repo##*/}
1052
1053SRCDEST=${SRCDEST:-$startdir}
1054PKGDEST=${PKGDEST:-$startdir}
1055
1056cd "$startdir" || die
1057. "$APKBUILD"
1058
1059# If REPODEST is set then it will override the PKGDEST
1060if [ -n "$REPODEST" ]; then
1061 PKGDEST="$REPODEST/$repo"
1062fi
1063
1064# If we are handling a sub package then reset subpackages and install
1065if [ -n "$subpkgname" ]; then
1066 origsubpackages="$subpackages"
1067 subpackages=
1068 install=
1069fi
1070pkgdir="$pkgbasedir/$pkgname"
1071controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname}
1072
1073trap 'die "Aborted by user"' INT
1074set_xterm_title "abuild: $pkgname"
1075
1076if [ -z "$1" ]; then
1077 set all
1078fi
1079
1080while [ $# -gt 0 ]; do
1081 runpart $1
1082 shift
1083done
1084
1085for i in $install_after; do
1086 post_add $i
1087done
1088
1089cleanup
1090