projects/aports·blob v2.23.0_rc1 · refs

2174 lines · 53.3 KiB

1#!/bin/sh
2
3# abuild - build apk packages (light version of makepkg)
4# Copyright (c) 2008-2015 Natanael Copa <[email protected]>
5#
6# Distributed under GPL-2
7#
8
9program_version=@VERSION@
10sysconfdir=@sysconfdir@
11abuildrepo_base=@abuildrepo@
12datadir=@datadir@
13
14abuild_path=$(readlink -f $0)
15
16if ! [ -f "$datadir/functions.sh" ]; then
17 echo "$datadir/functions.sh: not found" >&2
18 exit 1
19fi
20. "$datadir/functions.sh"
21
22# defaults
23BUILD_BASE="build-base"
24
25: ${FAKEROOT:="fakeroot"}
26: ${SUDO_APK:="abuild-apk"}
27: ${APK:="apk"}
28: ${ADDUSER:="abuild-adduser"}
29: ${ADDGROUP:="abuild-addgroup"}
30
31apk_opt_wait="--wait 30"
32
33# run optional log command for remote logging
34logcmd() {
35 ${ABUILD_LOG_CMD:-true} "$@"
36 return 0
37}
38
39# we override the default msg, warning and error as we want the pkgname
40msg() {
41 [ -n "$quiet" ] && return 0
42 local prompt="$GREEN>>>${NORMAL}"
43 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
44 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
45 printf "${prompt} ${name}${fake}: %s\n" "$1" >&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}: %s\n" "$1" >&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}: %s\n" "$1" >&2
60 logcmd "ERROR: $pkgname: $1"
61}
62
63cross_compiling() {
64 test "$CBUILD" != "$CHOST" -a -n "$CBUILDROOT"
65}
66
67cleanup() {
68 local i=
69 set_xterm_title ""
70 if [ -n "$CLEANUP_FILES" ]; then
71 rm -f $CLEANUP_FILES
72 fi
73 for i; do
74 case $i in
75 pkgdir) msg "Cleaning up pkgdir"; rm -rf "$pkgbasedir";;
76 srcdir) msg "Cleaning up srcdir"; rm -rf "$srcdir";;
77 deps)
78 if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then
79 msg "Uninstalling dependencies..."
80 $SUDO_APK del --quiet $apk_opt_wait $uninstall_after
81 if cross_compiling; then
82 $SUDO_APK del --root "$CBUILDROOT" \
83 --quiet $apk_opt_wait \
84 $uninstall_after
85 fi
86 fi
87 ;;
88 esac
89 done
90}
91
92die() {
93 error "$@"
94 cleanup $ERROR_CLEANUP
95 exit 1
96}
97
98spell_error() {
99 die "APKBUILD contains '$1'. It should be '$2'"
100}
101
102# check if apkbuild is basicly sane
103default_sanitycheck() {
104 local i= j= suggestion=
105 msg "Checking sanity of $APKBUILD..."
106 [ -z "$pkgname" ] && die "Missing pkgname in APKBUILD"
107 [ -z "${pkgname##* *}" ] && die "pkgname contains spaces"
108 [ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
109 if [ "$pkgver" != "volatile" ] && [ -z "$nodeps" ]; then
110 $APK version --check --quiet "$pkgver" ||\
111 die "$pkgver is not a valid version"
112 fi
113 [ -z "$pkgrel" ] && die "Missing pkgrel in APKBUILD"
114 [ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD"
115 [ -z "$url" ] && die "Missing url in APKBUILD"
116 [ -z "$license" ] && die "Missing license in APKBULID"
117 if [ $(echo "$pkgdesc" | wc -c) -gt 128 ]; then
118 die "pkgdesc is too long"
119 fi
120 is_function package || warning "Missing package() function in APKBUILD"
121
122 if [ -n "$replaces_priority" ] \
123 && ! echo $replaces_priority | egrep -q '^[0-9]+$'; then
124 die "replaces_priority must be a number"
125 fi
126 # check so no package names starts with -
127 for i in $pkgname $subpackages; do
128 case $i in
129 -*) die "${i%:*} is not a valid package name";;
130 esac
131 done
132
133 # check if CARCH, CBUILD, CHOST and CTARGET is set
134 [ -z "$CHOST" ] && die "Please set CHOST in /etc/abuild.conf"
135
136 if [ -z "$CARCH" ]; then
137 die "Please fix CHOST, or set CARCH in abuild.conf"
138 fi
139
140 for i in $install; do
141 local n=${i%.*}
142 local suff=${i##*.}
143 case "$suff" in
144 pre-install|post-install|pre-upgrade|post-upgrade|pre-deinstall|post-deinstall);;
145 *) die "$i: unknown install script suffix"
146 esac
147 if ! subpackages_has "$n" && [ "$n" != "$pkgname" ]; then
148 die "$i: install script does not match pkgname or any subpackage"
149 fi
150 [ -e "$startdir/$i" ] || die "install script $i is missing"
151 for j in chown chmod chgrp; do
152 if grep -q $j "$startdir"/$i; then
153 warning "$i: found $j"
154 warning2 "Permissions should be fixed in APKBUILD package()"
155 fi
156 done
157 done
158
159 for i in $triggers; do
160 local f=${i%=*}
161 local p=${f%.trigger}
162 [ "$f" = "$i" ] && die "$f: triggers must contain '='"
163 [ "$p" = "$f" ] && die "$f: triggers scripts must have .trigger suffix"
164 if ! subpackages_has "$p" && [ "$p" != "$pkgname" ]; then
165 die "$p: trigger script does not match pkgname or any subpackage"
166 fi
167
168 [ -e "$startdir"/$f ] || die "trigger script $f is missing"
169 done
170 if [ -n "$source" ]; then
171 for i in $source; do
172 if install_has "$i"; then
173 warning "You should not have \$install in source"
174 continue
175 fi
176 case "$i" in
177 *::*) i=${i%%::*};;
178 https://*) makedepends_has wget && warning "wget no longer need to be in makedepends when source has https://" ;;
179 esac
180 list_has ${i##*/} $md5sums $sha256sums $sha512sums \
181 || die "${i##*/} is missing in checksums"
182
183 # verify that our source does not have git tag version
184 # name as tarball (typicallly github)
185 if is_remote "$i" && [ "${i#*::}" = "$i" ]; then
186 case ${i##*/} in
187 v$pkgver.tar.*|$pkgver.tar.*)
188 die "source ${i##*/} needs to be renamed to avoid possible collisions"
189 ;;
190 esac
191 fi
192 done
193 fi
194
195 # verify that things listed in checksum also is listed in source
196 local algo=
197 for algo in md5 sha256 sha512; do
198 eval set -- \$${algo}sums
199 while [ $# -gt 1 ]; do
200 local file="$2"
201 shift 2
202 source_has $file || die "$file exists in ${algo}sums but is missing in source"
203 done
204 done
205
206 # common spelling errors
207 [ -n "$depend" ] && spell_error depend depends
208 [ -n "$makedepend" ] && spell_error makedepend makedepends
209 [ -n "$pkguser" ] && spell_error pkguser pkgusers
210 [ -n "$pkggroup" ] && spell_error pkggroup pkggroups
211 [ -n "$subpackage" ] && spell_error subpackage subpackages
212
213 grep '^# Maintainer:' $APKBUILD >/dev/null || warning "No maintainer"
214
215 makedepends_has 'g++' && warning "g++ should not be in makedepends"
216 return 0
217}
218
219sanitycheck() {
220 default_sanitycheck
221}
222
223sumcheck() {
224 local algo="$1" sums="$2"
225 local dummy f endreturnval originalparams origin file
226
227 # get number of checksums
228 set -- $sums
229 local numsums=$(( $# / 2 ))
230
231 set -- $source
232 if [ $# -ne $numsums ]; then
233 die "Number of ${algo}sums($numsums) does not correspond to number of sources($#)"
234 fi
235 fetch || return 1
236 msg "Checking ${algo}sums..."
237 cd "$srcdir" || return 1
238 IFS=$'\n'
239 endreturnval=0
240 for src in $sums; do
241 origin=$1; shift
242 echo "$src" | ${algo}sum -c
243 if [ $? -ne 0 ]; then
244 endreturnval=1
245 is_remote $origin || continue
246 echo "Because the remote file above failed the ${algo}sum check it will be deleted."
247 echo "Rebuilding will cause it to re-download which in some cases may fix the problem."
248 file=`echo "$src" | sed 's/.*[ \t\n]\(.*\)/\1/'`
249 echo "Deleting: $file"
250 rm $file
251 fi
252 done
253 unset IFS
254 return $endreturnval
255}
256
257# for compatibility
258md5check() {
259 warning "'md5check' is deprecated. Use 'verify' instead"
260 sumcheck md5 "$md5sums"
261}
262
263# verify checksums
264verify() {
265 local verified=false algo=
266 for algo in sha512 sha256 sha1 md5; do
267 local sums=
268 eval sums=\"\$${algo}sums\"
269 if [ -z "$sums" ] || [ -z "$source" ]; then
270 continue
271 fi
272 sumcheck "$algo" "$sums" || return 1
273 verified=true
274 break
275 done
276 if [ -n "$source" ] && ! $verified; then
277 die "Use 'abuild checksum' to generate/update the checksum(s)"
278 fi
279 return 0
280}
281
282# verify upstream sources
283sourcecheck() {
284 local uri
285 for uri in $source; do
286 is_remote $uri || continue
287 case "$uri" in
288 saveas-*://*)
289 uri=${uri#saveas-}
290 uri=${uri%/*}
291 ;;
292 *::*)
293 uri=${uri##*::}
294 ;;
295 esac
296 wget -q -s "$uri" || return 1
297 done
298 return 0
299}
300
301# convert curl options to wget options and call wget instead of curl
302wget_fallback() {
303 local wget_opts= outfile= opt=
304 while getopts "C:Lko:s" opt; do
305 case $opt in
306 'L') ;; # --location. wget does this by default
307 'f') ;; # --fail. wget does this by default
308 'C') wget_opts="$wget_opts -c";; # --continue-at
309 's') wget_opts="$wget_opts -q";; # --silent
310 'o') wget_opts="$wget_opts -O $OPTARG";; # --output
311 'k') wget_opts="$wget_opts --no-check-certificate";; #gnu wget
312 esac
313 done
314 shift $(( $OPTIND - 1 ))
315 wget $wget_opts "$1"
316}
317
318uri_fetch() {
319 local uri="$1"
320 local d="${uri##*/}" # $(basename $uri)
321 local opts
322 [ -n "$quiet" ] && opts="-s"
323
324 local lockfile="$SRCDEST/$d".lock
325
326 # fix saveas-*://* URIs
327 case "$uri" in
328 # remove 'saveas-' from beginning and
329 # '/filename' from end of URI
330 saveas-*://*) uri="${uri:7:$(expr ${#uri} - 7 - ${#d} - 1)}";;
331
332 *::*)
333 d=${uri%%::*}
334 uri=${uri#$d::}
335 ;;
336 esac
337
338 case "$uri" in
339 https://*) opts="-k";;
340 esac
341
342 mkdir -p "$SRCDEST"
343
344 CLEANUP_FILES="$CLEANUP_FILES $lockfile"
345 (
346 flock -n -x 9 || msg "Waiting for ${lockfile##*/}..."
347 flock -x 9
348
349 [ -f "$SRCDEST/$d" ] && exit 0 # use exit since its a subshell
350
351 if [ -f "$SRCDEST/$d.part" ]; then
352 msg "Partial download found. Trying to resume"
353 opts="$opts -C -"
354 fi
355 msg "Fetching $uri"
356
357 # fallback to wget if curl is missing. useful for bootstrapping
358 local fetcher=
359 if ! [ -x "$(which curl)" ]; then
360 fetcher=wget_fallback
361 else
362 fetcher=curl
363 opts="$opts -L -f -k"
364 fi
365
366 $fetcher $opts -o "$SRCDEST/$d.part" "$uri" \
367 && mv "$SRCDEST/$d.part" "$SRCDEST/$d"
368
369 ) 9>$lockfile
370
371 local rc=$?
372 rm -f "$lockfile"
373 return $rc
374}
375
376is_remote() {
377 case "${1#*::}" in
378 http://*|ftp://*|https://*|saveas-*://*)
379 return 0;;
380 esac
381 return 1
382}
383
384filename_from_uri() {
385 local uri="$1"
386 local filename="${uri##*/}" # $(basename $uri)
387 case "$uri" in
388 *::*) filename=${uri%%::*};;
389 esac
390 echo "$filename"
391}
392
393# try download from file from mirror first
394uri_fetch_mirror() {
395 local uri="$1"
396 if [ -n "$DISTFILES_MIRROR" ]; then
397 if is_remote "$DISTFILES_MIRROR"; then
398 uri_fetch "$DISTFILES_MIRROR"/$(filename_from_uri $uri)\
399 && return 0
400 else
401 cp "$DISTFILES_MIRROR"/$(filename_from_uri $uri) \
402 "$SRCDEST" && return 0
403 fi
404 fi
405 uri_fetch "$uri"
406}
407
408default_fetch() {
409 local s
410 mkdir -p "$srcdir"
411 for s in $source; do
412 if is_remote "$s"; then
413 uri_fetch_mirror "$s" || return 1
414 ln -sf "$SRCDEST/$(filename_from_uri $s)" "$srcdir"/
415 else
416 ln -sf "$startdir/$s" "$srcdir/"
417 fi
418 done
419}
420
421fetch() {
422 default_fetch
423}
424
425# verify that all init.d scripts are openrc runscripts
426initdcheck() {
427 local i line
428 for i in $source; do
429 case $i in
430 *.initd) line=$(head -n 1 "$srcdir"/$i);;
431 *) continue ;;
432 esac
433
434 case "$line" in
435 *sbin/openrc-run)
436 ;;
437 *sbin/runscript)
438 warning "$i is not an openrc #!/sbin/openrc-run"
439 ;;
440 *) error "$i is not an openrc #!/sbin/openrc-run"
441 return 1
442 ;;
443 esac
444 done
445}
446
447# unpack the sources
448default_unpack() {
449 local u
450 if [ -z "$force" ]; then
451 verify || return 1
452 initdcheck || return 1
453 fi
454 mkdir -p "$srcdir"
455 for u in $source; do
456 local s="$SRCDEST/$(filename_from_uri $u)"
457 case "$s" in
458 *.tar)
459 msg "Unpacking $s..."
460 tar -C "$srcdir" -xf "$s" || return 1;;
461 *.tar.gz|*.tgz)
462 msg "Unpacking $s..."
463 tar -C "$srcdir" -zxf "$s" || return 1;;
464 *.tar.bz2)
465 msg "Unpacking $s..."
466 tar -C "$srcdir" -jxf "$s" || return 1;;
467 *.tar.lzma)
468 msg "Unpacking $s..."
469 unlzma -c "$s" | tar -C "$srcdir" -x \
470 || return 1;;
471 *.tar.xz)
472 msg "Unpacking $s..."
473 unxz -c "$s" | tar -C "$srcdir" -x || return 1;;
474 *.zip)
475 msg "Unpacking $s..."
476 unzip "$s" -d "$srcdir" || return 1;;
477 esac
478 done
479}
480
481unpack() {
482 default_unpack
483}
484
485# cleanup source and package dir
486clean() {
487 msg "Cleaning temporary build dirs..."
488 rm -rf "$srcdir"
489 rm -rf "$pkgbasedir"
490}
491
492# cleanup fetched sources
493cleancache() {
494 local s
495 for s in $source; do
496 if is_remote "$s"; then
497 s=$(filename_from_uri $s)
498 msg "Cleaning downloaded $s ..."
499 rm -f "$SRCDEST/$s"
500 fi
501 done
502}
503
504listpkgnames() {
505 local i
506 for i in $pkgname $subpackages; do
507 echo ${i%:*}
508 done
509 for i in $linguas; do
510 echo $pkgname-lang-$i
511 done
512}
513
514cleanpkg() {
515 local i
516 getpkgver || return 1
517 msg "Cleaning built packages..."
518 for i in $(listpkgnames); do
519 local p="${i%:*}-$pkgver-r$pkgrel"
520 rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz" \
521 "$abuildrepo"/$p.apk "$abuildrepo"/*/$p.apk
522 done
523 # remove given packages from index
524 update_abuildrepo_index
525}
526
527# clean all packages except current
528cleanoldpkg() {
529 local i j
530 getpkgver || return 1
531 msg "Cleaning all packages except $pkgver-r$pkgrel..."
532 for i in $(listpkgnames); do
533 local pn=${i%:*}
534 for j in "$PKGDEST"/$pn-[0-9]*.apk ; do
535 [ "$j" = "$PKGDEST/$pn-$pkgver-r$pkgrel.apk" ] \
536 && continue
537 rm -f "$j" "$abuildrepo"/*/${j##*/}
538 done
539 done
540 update_abuildrepo_index
541 return 0
542}
543
544mkusers() {
545 local i
546 for i in $pkggroups; do
547 if ! getent group $i >/dev/null; then
548 msg "Creating group $i"
549 $ADDGROUP -S $i || return 1
550 fi
551 done
552 for i in $pkgusers; do
553 if ! getent passwd $i >/dev/null; then
554 local gopt=
555 msg "Creating user $i"
556 if getent group $i >/dev/null; then
557 gopt="-G $i"
558 fi
559 $ADDUSER -S -D -H $gopt $i || return 1
560 fi
561 done
562}
563
564# helper to update config.sub to a recent version
565update_config_sub() {
566 local changed=false
567 find . -name config.sub | while read f; do
568 if ! ./$f armv6-alpine-linux-muslgnueabihf 2>/dev/null; then
569 msg "Updating $f"
570 cp "$datadir"/${f##*/} "$f" || return 1
571 changed=true
572 else
573 msg "No update needed for $f"
574 fi
575 # pipe subshell will return status of last command
576 $changed
577 done
578 return $?
579}
580
581runpart() {
582 local part=$1
583 [ -n "$DEBUG" ] && msg "$part"
584 $part || die "$part failed"
585}
586
587# override those in your build script
588getpkgver() {
589 # this func is supposed to be overridden by volatile packages
590 if [ "$pkgver" = "volatile" ]; then
591 error "Please provide a getpkgver() function in your APKBUILD"
592 return 1
593 fi
594}
595
596prepare() {
597 :
598}
599
600build() {
601 :
602}
603
604# generate a simple tar.gz package of pkgdir
605targz() {
606 cd "$pkgdir" || return 1
607 mkdir -p "$PKGDEST"
608 tar -czf "$PKGDEST"/$pkgname-$pkgver-r$pkgrel.tar.gz *
609}
610
611get_split_func() {
612 # get the 'func' from "sub-pkg:func"
613 local func=${1##*:}
614
615 # get 'func' from "sub-pkg-func" if there was no :func
616 [ "$func" = "$1" ] && func=${func##*-}
617 echo $func
618}
619
620postcheck() {
621 local dir="$1" name="$2" i=
622 msg "Running postcheck for $name"
623 # checking for FHS compat
624 if ! options_has "!fhs"; then
625 for i in "$dir"/srv/* "$dir"/usr/local/* "$dir"/opt/*; do
626 if [ -e "$i" ]; then
627 error "Packages must not put anything under /srv, /usr/local or /opt"
628 return 1
629 fi
630 done
631 if [ -d "$dir"/usr/var ]; then
632 error "Found /usr/var, localstatedir is most likely wrong"
633 return 1
634 fi
635 fi
636
637 # remove *.la files if libtool is not set
638 if ! options_has "libtool"; then
639 find "$dir" -name '*.la' -type f -delete
640 fi
641
642 # look for /usr/lib/charset.alias
643 if [ -e "$dir"/usr/lib/charset.alias ] \
644 && ! options_has "charset.alias"; then
645 error "Found /usr/lib/charset.alias"
646 return 1
647 fi
648 # check directory permissions
649 i=$(find "$dir" -type d -perm -777 | sed "s|^$dir|\t|")
650 if [ -n "$i" ]; then
651 warning "World writeable directories found:"
652 echo "$i"
653 fi
654 # check so we dont have any suid root binaries that are not PIE
655 i=$(find "$dir" -type f -perm +6000 \
656 | xargs scanelf --nobanner --etype ET_EXEC \
657 | sed "s|ET_EXEC $dir|\t|")
658 if [ -n "$i" ]; then
659 error "Found non-PIE files that has SUID:"
660 echo "$i"
661 return 1
662 fi
663 # test suid bit on executable
664 if ! options_has "suid"; then
665 i=$(find "$dir" \( -perm -u+s -o -perm -g+s \) -a -type f \
666 -a -perm -o+x)
667 if [ -n "$i" ]; then
668 error "Found executable files with SUID bit set:"
669 echo "$i"
670 return 1
671 fi
672 fi
673
674 # test for textrels
675 if ! options_has "textrels"; then
676 local res="$(scanelf --recursive --textrel --quiet "$dir")"
677 if [ -n "$res" ]; then
678 error "Found textrels:"
679 echo "$res"
680 return 1
681 fi
682 fi
683 return 0
684}
685
686prepare_subpackages() {
687 local i
688 cd "$startdir"
689 for i in $subpackages; do
690 local func=$(get_split_func $i)
691 # call abuild recursively, setting subpkg{dir,name}
692 msg "Running split function $func..."
693 local dir="$pkgbasedir/${i%:*}" name="${i%:*}"
694 ( subpkgdir="$dir" subpkgname="$name" \
695 $0 $func prepare_package \
696 && postcheck "$dir" "$name" ) || return 1
697 done
698 postcheck "$pkgdir" "$pkgname" || return 1
699 # post check for /usr/share/locale
700 if [ -d "$pkgdir"/usr/share/locale ]; then
701 warning "Found /usr/share/locale"
702 warning2 "Maybe add \$pkgname-lang to subpackages?"
703 fi
704}
705
706default_lang() {
707 pkgdesc="Languages for package $pkgname"
708 install_if="$pkgname=$pkgver-r$pkgrel lang"
709 arch="noarch"
710 local dir
711 for dir in ${langdir:-/usr/share/locale}; do
712 mkdir -p "$subpkgdir"/${dir%/*}
713 mv "$pkgdir"/"$dir" "$subpkgdir"/"$dir" || return 1
714 done
715}
716
717lang() {
718 default_lang
719}
720
721default_lang_subpkg() {
722 if [ -z "$lang" ]; then
723 error "lang is not set"
724 return 1
725 fi
726 pkgdesc="$pkgname language pack for $lang"
727 arch="noarch"
728 install_if="$pkgname=$pkgver-r$pkgrel lang-$lang"
729 local dir
730 for dir in ${langdir:-/usr/share/locale}; do
731 mkdir -p "$subpkgdir"/$dir
732 mv "$pkgdir"/$dir/$lang* \
733 "$subpkgdir"/$dir/ \
734 || return 1
735 done
736}
737
738lang_subpkg() {
739 default_lang_subpkg
740}
741
742prepare_language_packs() {
743 for lang in $linguas; do
744 lang="$lang" \
745 subpkgname="$pkgname-lang-$lang" \
746 subpkgdir="$pkgbasedir"/$subpkgname \
747 $0 lang_subpkg prepare_package || return 1
748 done
749}
750
751# echo '-dirty' if git is not clean
752git_dirty() {
753 if [ $(git status -s "$startdir" | wc -l) -ne 0 ]; then
754 echo "-dirty"
755 fi
756}
757
758# echo last commit hash id
759git_last_commit() {
760 git log --format=oneline -n 1 "$startdir" | awk '{print $1}'
761}
762
763get_maintainer() {
764 if [ -z "$maintainer" ]; then
765 maintainer=$(awk -F': ' '/\# *Maintainer/ {print $2}' "$APKBUILD")
766 fi
767}
768
769prepare_metafiles() {
770 getpkgver || return 1
771 local name=${subpkgname:-$pkgname}
772 [ -z "${name##* *}" ] && die "package name contains spaces"
773 local dir=${subpkgdir:-$pkgdir}
774 local pkg="$name-$pkgver-r$pkgrel.apk"
775 local pkginfo="$controldir"/.PKGINFO
776 local sub
777
778 [ ! -d "$dir" ] && die "Missing $dir"
779 cd "$dir"
780 mkdir -p "$controldir"
781 local builddate=$(date -u "+%s")
782 local size=$(du -sk | awk '{print $1 * 1024}')
783 local parch="$CARCH"
784
785 # we need to wait with setting noarch til our build infra can handle it
786# if [ "$arch" = "noarch" ]; then
787# parch="noarch"
788# fi
789
790 echo "# Generated by $(basename $0) $program_version" >"$pkginfo"
791 if [ -n "$FAKEROOTKEY" ]; then
792 echo "# using $($FAKEROOT -v)" >> "$pkginfo"
793 fi
794 echo "# $(date -u)" >> "$pkginfo"
795 cat >> "$pkginfo" <<EOF
796pkgname = $name
797pkgver = $pkgver-r$pkgrel
798pkgdesc = $pkgdesc
799url = $url
800builddate = $builddate
801packager = ${PACKAGER:-"Unknown"}
802size = $size
803arch = $parch
804origin = $pkgname
805EOF
806 local i deps
807 deps="$depends"
808 if [ "$pkgname" != "busybox" ] && ! depends_has busybox; then
809 for i in $install $triggers; do
810 local s=${i%=*}
811 [ "$name" != "${s%.*}" ] && continue
812 if head -n 1 "$startdir/$s" | grep '^#!/bin/sh' >/dev/null ; then
813 msg "Script found. busybox added as a dependency for $pkg"
814 deps="$deps busybox"
815 break
816 fi
817 done
818 fi
819
820 # store last_commit in global var so we only call git once
821 if [ -z "$last_commit" ]; then
822 last_commit="$(git_last_commit)$(git_dirty)"
823 fi
824 echo "commit = $last_commit" >> "$pkginfo"
825
826 get_maintainer
827 if [ -n "$maintainer" ]; then
828 echo "maintainer = $maintainer" >> "$pkginfo"
829 fi
830
831 if [ -n "$replaces_priority" ]; then
832 echo "replaces_priority = $replaces_priority" >> "$pkginfo"
833 fi
834
835 echo "license = $license" >> "$pkginfo"
836 for i in $replaces; do
837 echo "replaces = $i" >> "$pkginfo"
838 done
839 for i in $deps; do
840 echo "depend = $i" >> "$pkginfo"
841 done
842 for i in $provides; do
843 echo "provides = $i" >> "$pkginfo"
844 done
845 for i in $triggers; do
846 local f=${i%=*}
847 local dirs=${i#*=}
848 [ "${f%.trigger}" != "$name" ] && continue
849 echo "triggers = ${dirs//:/ }" >> "$pkginfo"
850 done
851 if [ -n "$install_if" ]; then
852 echo "install_if = $(echo $install_if)" >> "$pkginfo"
853 fi
854
855 local metafiles=".PKGINFO"
856 for i in $install $triggers; do
857 local f=${i%=*}
858 local n=${f%.*}
859 if [ "$n" != "$name" ]; then
860 continue
861 fi
862 script=${f#$name}
863 msg "Adding $script"
864 cp "$startdir/$f" "$controldir/$script" || return 1
865 chmod +x "$controldir/$script"
866 metafiles="$metafiles $script"
867 done
868 echo $metafiles | tr ' ' '\n' > "$controldir"/.metafiles
869}
870
871prepare_trace_rpaths() {
872 local dir=${subpkgdir:-$pkgdir}
873 local etype= soname= file= sover=
874 [ "$arch" = "noarch" ] && return 0
875 options_has "!tracedeps" && return 0
876 # lets tell all the places we should look for .so files - all rpaths
877 scanelf --quiet --recursive --rpath "$dir" \
878 | sed -e 's/[[:space:]].*//' -e 's/:/\n/' | sort -u \
879 >"$controldir"/.rpaths
880 if grep -q -x '/usr/lib' "$controldir"/.rpaths; then
881 warning "Redundant /usr/lib in rpath found"
882 fi
883 if grep '^/home/' "$controldir"/.rpaths; then
884 error "Has /home/... in rpath"
885 return 1
886 fi
887}
888
889# search for broken symlinks so we later can pull in proper depends
890prepare_symlinks() {
891 local dir="${subpkgdir:-$pkgdir}"
892 options_has "!tracedeps" && return 0
893 cd "$dir" || return 1
894 find -type l | while read symlink; do
895 if ! [ -e "$symlink" ]; then
896 echo "$symlink $(readlink $symlink)" \
897 >> "$controldir"/.symlinks
898 fi
899 done
900}
901
902prepare_pkgconfig_provides() {
903 local dir="${subpkgdir:-$pkgdir}"
904 options_has "!tracedeps" && return 0
905 cd "$dir" || return 1
906 for i in usr/lib/pkgconfig/*.pc; do
907 if ! [ -e "$i" ]; then
908 continue
909 fi
910 local f=${i##*/}
911 local v=$(PKG_CONFIG_PATH="$dir"/usr/lib/pkgconfig pkg-config \
912 --modversion ${f%.pc})
913 echo "${f%.pc}=${v:-0}" >> "$controldir"/.provides-pc
914 done
915}
916
917# check if dir has arch specific binaries
918dir_has_arch_binaries() {
919 local dir="$1"
920 # if scanelf returns something, then we have binaries
921 [ -n "$(scanelf -R "$dir" | head -n 1)" ] && return 0
922
923 # look for static *.a
924 [ -n "$(find "$dir" -type f -name '*.a' | head -n 1)" ] && return 0
925
926 return 1
927}
928
929# returns true if this is the -dev package
930is_dev_pkg() {
931 test "${subpkgname%-dev}" != "$subpkgname"
932}
933
934# check that noarch is set if needed
935archcheck() {
936 options_has "!archcheck" && return 0
937 if dir_has_arch_binaries "${subpkgdir:-$pkgdir}"; then
938 [ "$arch" != "noarch" ] && return 0
939 error "Arch specific binaries found so arch must not be set to \"noarch\""
940 return 1
941 elif [ "$arch" != "noarch" ] && ! is_dev_pkg; then
942 # we dont want -dev package go to noarch
943 warning "No arch specific binaries found so arch should probably be set to \"noarch\""
944 fi
945 return 0
946}
947
948prepare_package() {
949 msg "Preparing ${subpkgname:+sub}package ${subpkgname:-$pkgname}..."
950 stripbin
951 prepare_metafiles \
952 && prepare_trace_rpaths \
953 && prepare_symlinks \
954 && prepare_pkgconfig_provides \
955 || return 1
956 archcheck
957}
958
959pkginfo_val() {
960 local key="$1"
961 local file="$2"
962 awk -F ' = ' "\$1 == \"$key\" {print \$2}" "$file"
963}
964
965# find real path to so files
966real_so_path() {
967 local so="$1"
968 shift
969 while [ $# -gt 0 ]; do
970 [ -e "$1"/$so ] && realpath "$1/$so" && return 0
971 shift
972 done
973 error "$so: path not found"
974 return 1
975}
976
977# search rpaths and /usr/lib /lib for given so files
978find_so_files() {
979 local rpaths=$(cat "$1")
980 shift
981 while [ $# -gt 0 ]; do
982 real_so_path "$1" /usr/lib /lib $rpaths || return 1
983 shift
984 done
985 return 0
986}
987
988subpkg_provides_so() {
989 grep -q -w "^$1" "$pkgbasedir"/.control.*/.provides-so 2>/dev/null
990}
991
992subpkg_provides_pc() {
993 grep -q -w "^$1" "$pkgbasedir"/.control.*/.provides-pc 2>/dev/null
994}
995
996trace_apk_deps() {
997 local name="$1"
998 local dir="$2"
999 local i= found= autodeps= deppkgs= missing=
1000 msg "Tracing dependencies..."
1001 # add pkgconfig if usr/lib/pkgconfig is found
1002 if [ -d "$pkgbasedir"/$name/usr/lib/pkgconfig ] \
1003 && ! grep -q '^depend = pkgconfig' "$dir"/.PKGINFO; then
1004 autodeps="$autodeps pkgconfig"
1005 fi
1006
1007 # special case for libpthread: we need depend on libgcc
1008 if [ "$CLIBC" = "uclibc" ] && [ -f "$dir"/.needs-so ] \
1009 && grep -q -w '^libpthread.so.*' "$dir"/.needs-so \
1010 && ! grep -q -w "^depend = libgcc" "$dir"/.PKGINFO; then
1011 autodeps="$autodeps libgcc"
1012 msg " added libgcc (due to libpthread)"
1013 fi
1014
1015 [ -f "$dir"/.needs-so ] && for i in $(cat "$dir"/.needs-so); do
1016 # first check if its provided by same apkbuild
1017 grep -q -w "^$i" "$dir"/.provides-so 2>/dev/null && continue
1018
1019 if subpkg_provides_so "$i" || cross_compiling \
1020 || $APK info --quiet --installed "so:$i"; then
1021 autodeps="$autodeps so:$i"
1022 else
1023 missing="$missing $i"
1024 fi
1025 done
1026
1027 # find all packages that holds the so files
1028 if [ -f "$dir"/.rpaths ]; then
1029 local so_files=$(find_so_files "$dir"/.rpaths $missing) \
1030 || return 1
1031 deppkgs=$($APK info --quiet --who-owns $so_files) || return 1
1032 fi
1033
1034 for found in $deppkgs; do
1035 if grep -w "^depend = ${found}$" "$dir"/.PKGINFO >/dev/null ; then
1036 warning "You can remove '$found' from depends"
1037 continue
1038 fi
1039 autodeps="$autodeps $found"
1040 done
1041
1042 # symlink targets
1043 for i in $(sort -u "$dir"/.symlinks-needs 2>/dev/null); do
1044 autodeps="$autodeps $i"
1045 done
1046
1047 # pkg-config depends
1048 for i in $(sort -u "$dir"/.needs-pc 2>/dev/null); do
1049 if subpkg_provides_pc "$i" || cross_compiling \
1050 || $APK info --quiet --installed "pc:$i"; then
1051 local provider=$(apk search --quiet "pc:$i")
1052 if list_has "$provider" $depends_dev; then
1053 warning "$provider should be removed from depends_dev"
1054 fi
1055 autodeps="$autodeps pc:$i"
1056 else
1057 warning "Could not find any provider for pc:$i"
1058 local pcfile=/usr/lib/pkgconfig/"${i%%[<>=]*}".pc
1059 if [ -e "$pcfile" ]; then
1060 local owner=$($APK info --quiet --who-owns $pcfile)
1061 warning "${owner:-package providing $pcfile} needs to be rebuilt"
1062 fi
1063 fi
1064 done
1065
1066 echo "# automatically detected:" >> "$dir"/.PKGINFO
1067 if [ -f "$dir"/.provides-so ]; then
1068 sed 's/^\(.*\) \([0-9].*\)/provides = so:\1=\2/' "$dir"/.provides-so \
1069 >> "$dir"/.PKGINFO
1070 fi
1071 if [ -f "$dir"/.provides-pc ]; then
1072 sed 's/^/provides = pc:/' "$dir"/.provides-pc | sort -u \
1073 >> "$dir"/.PKGINFO
1074 fi
1075 [ -z "$autodeps" ] && return 0
1076 for i in $autodeps; do
1077 echo "depend = $i"
1078 done | sort -u >> "$dir"/.PKGINFO
1079 # display all depends
1080 sed -n '/^depend =/s/depend = /\t/p' "$dir"/.PKGINFO >&2
1081}
1082
1083find_scanelf_paths() {
1084 local datadir="$1"
1085 local paths="$datadir/lib:$datadir/usr/lib" i= rpaths=
1086 if [ -n "$ldpath" ]; then
1087 paths="$paths:$(echo "${datadir}${ldpath}" | sed "s|:|:$datadir|g")"
1088 fi
1089 # search in all rpaths
1090 for rpaths in "$pkgbasedir"/.control.*/.rpaths; do
1091 [ -f "$rpaths" ] || continue
1092 while read i; do
1093 local dir="${datadir}${i}"
1094 IFS=:
1095 if [ -d "$dir" ] && ! list_has "$dir" $paths; then
1096 paths="$paths:${dir}"
1097 fi
1098 unset IFS
1099 done < "$rpaths"
1100 done
1101 echo "$paths"
1102}
1103
1104scan_shared_objects() {
1105 local name="$1" controldir="$2" datadir="$3"
1106 local opt= i=
1107
1108 if [ "$arch" = "noarch" ]; then
1109 return 0
1110 fi
1111
1112 # allow spaces in paths
1113 IFS=:
1114 set -- $(find_scanelf_paths "$datadir")
1115 unset IFS
1116
1117 # sanity check, verify that each path is prefixed with datadir
1118 for i; do
1119 if [ "${i#$datadir}" = "$i" ]; then
1120 error "Internal error in scanelf paths"
1121 return 1
1122 fi
1123 done
1124
1125 if options_has "ldpath-recursive"; then
1126 opt="--recursive"
1127 fi
1128 msg "Scanning shared objects"
1129 # lets tell all the .so files this package provides in .provides-so
1130 scanelf --nobanner --soname $opt "$@" | while read etype soname file; do
1131 # if soname field is missing, soname will be the filepath
1132 sover=0
1133 if [ -z "$file" ]; then
1134 file="$soname"
1135 soname=${soname##*/}
1136 fi
1137
1138 # we only want shared libs
1139 case $soname in
1140 *.so|*.so.[0-9]*|*.c32);;
1141 *) continue;;
1142 esac
1143
1144 case "$file" in
1145 *.so.[0-9]*) sover=${file##*.so.};;
1146 *.so)
1147 # filter out sonames with version when file does not
1148 # have version
1149 case "$soname" in
1150 *.so.[0-9]*)
1151 if options_has "sover-namecheck"; then
1152 continue
1153 fi
1154 esac
1155 ;;
1156 esac
1157 list_has "$soname" $somask && continue
1158 echo "$soname $sover"
1159 # use awk to filter out dupes that has sover = 0
1160 done | awk '{ if (so[$1] == 0) so[$1] = $2; }
1161 END { for (i in so) print(i " " so[i]); }' \
1162 | sort -u > "$controldir"/.provides-so
1163
1164 # verify that we dont have any duplicates
1165 local dupes="$(cut -d' ' -f1 "$controldir"/.provides-so | uniq -d)"
1166 if [ -n "$dupes" ]; then
1167 die "provides multiple versions of same shared object: $dupes"
1168 fi
1169
1170 # now find the so dependencies
1171 scanelf --nobanner --recursive --needed "$datadir" | tr ' ' ':' \
1172 | awk -F ":" '$2 != "" && ($1 == "ET_DYN" || $1 == "ET_EXEC") {print $2}' \
1173 | sed 's:,:\n:g' | sort -u \
1174 | while read soname; do
1175 # only add files that are not self provided
1176 grep -q -w "^$soname" "$controldir"/.provides-so \
1177 || list_has "$soname" $somask \
1178 || echo $soname
1179 done > "$controldir"/.needs-so
1180}
1181
1182# normalize a path string
1183normalize_path() {
1184 local oifs="$IFS" pathstr= i=
1185 IFS='/'
1186 set -- $1
1187 for i; do
1188 case "$i" in
1189 "."|"") continue;;
1190 "..") pathstr="${pathstr%%/${pathstr##*/}}";;
1191 *) pathstr="${pathstr}/$i";;
1192 esac
1193 done
1194 echo "$pathstr"
1195}
1196
1197# find which package provides file that symlink points to
1198scan_symlink_targets() {
1199 local name="$1" dir="$2" datadir="$3"
1200 local symfile= targetpath=
1201 cd "$datadir"
1202 for symfile in "$pkgbasedir"/.control.*/.symlinks; do
1203 [ -e "$symfile" ] || continue
1204 while read symlink target; do
1205 if [ "${target#/}" = "$target" ]; then
1206 target="${symlink%/*}/$target"
1207 fi
1208 targetpath="$datadir"/$(normalize_path "$target")
1209 if [ -e "$targetpath" ] || [ -L "$targetpath" ]; then
1210 local d="${symfile%/.symlinks}"
1211 echo "$name=$pkgver-r$pkgrel" \
1212 >> "$d"/.symlinks-needs
1213 fi
1214 done < "$symfile"
1215 done
1216}
1217
1218#find pkg-config dependencies
1219scan_pkgconfig_depends() {
1220 local provides_pc="$1" controldir= name= datadir=
1221 [ -e "$provides_pc" ] || return 0
1222 controldir="${provides_pc%/*}"
1223 name="$(pkginfo_val pkgname "$controldir"/.PKGINFO)"
1224 datadir="$pkgbasedir"/$name
1225 for i in $(sort -u "$provides_pc"); do
1226 PKG_CONFIG_PATH="$datadir"/usr/lib/pkgconfig pkg-config \
1227 --print-requires \
1228 --print-requires-private ${i%=*} \
1229 | sed -E 's/\s*([<>=]+)\s*/\1/' \
1230 | while read pc; do
1231 # only add files that are not self provided
1232 if ! grep -q -w "^${pc%[<>=]*}" "$provides_pc"; then
1233 echo "$pc" >> "$controldir"/.needs-pc
1234 fi
1235 done
1236 done
1237}
1238
1239# read size in bytes from stdin and show as human readable
1240human_size() {
1241 awk '{ split("B KB MB GB TB PB", type)
1242 for(i=5; y < 1; i--)
1243 y = $1 / (2**(10*i))
1244 printf("%.1f %s\n", y, type[i+2]) }'
1245}
1246
1247create_apks() {
1248 local file= dir= name= ver= apk= datadir= size=
1249 getpkgver || return 1
1250 mkdir -p "$PKGDEST"
1251 if ! options_has "!tracedeps"; then
1252 for file in "$pkgbasedir"/.control.*/.PKGINFO; do
1253 dir="${file%/.PKGINFO}"
1254 name="$(pkginfo_val pkgname $file)"
1255 datadir="$pkgbasedir"/$name
1256 subpkgname=$name
1257 scan_shared_objects "$name" "$dir" "$datadir"
1258 scan_symlink_targets "$name" "$dir" "$datadir"
1259 done
1260 for file in "$pkgbasedir"/.control.*/.provides-pc; do
1261 scan_pkgconfig_depends "$file"
1262 done
1263 fi
1264
1265 for file in "$pkgbasedir"/.control.*/.PKGINFO; do
1266 dir="${file%/.PKGINFO}"
1267 name=$(pkginfo_val pkgname $file)
1268 ver=$(pkginfo_val pkgver $file)
1269 size=$(pkginfo_val size $file | human_size)
1270 apk=$name-$ver.apk
1271 datadir="$pkgbasedir"/$name
1272 subpkgname=$name
1273
1274 trace_apk_deps "$name" "$dir" || return 1
1275 msg "Package size: ${size}"
1276 msg "Compressing data..."
1277 (
1278 cd "$datadir"
1279 # data.tar.gz
1280 set -- *
1281 if [ "$1" = '*' ]; then
1282 touch .dummy
1283 set -- .dummy
1284 fi
1285 tar --xattrs -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz
1286
1287 msg "Create checksum..."
1288 # append the hash for data.tar.gz
1289 local sha256=$(sha256sum "$dir"/data.tar.gz | cut -f1 -d' ')
1290 echo "datahash = $sha256" >> "$dir"/.PKGINFO
1291
1292 # control.tar.gz
1293 cd "$dir"
1294 tar -c $(cat "$dir"/.metafiles) | abuild-tar --cut \
1295 | gzip -9 > control.tar.gz
1296 abuild-sign -q control.tar.gz || exit 1
1297
1298 msg "Create $apk"
1299 # create the final apk
1300 cat control.tar.gz data.tar.gz > "$PKGDEST"/$apk
1301 )
1302 done
1303 subpkgname=
1304}
1305
1306clean_abuildrepo() {
1307 local apk
1308 cd "$abuildrepo" || return 1
1309
1310 # remove compat symlink
1311 for d in "$abuildrepo/$CARCH"; do
1312 [ -L "$d" ] && rm "$d"
1313 done
1314
1315 # remove broken links from abuildrepo
1316 for apk in *.apk */*.apk; do
1317 if [ -L "$apk" ] && [ ! -f "$apk" ]; then
1318 rm -f "$apk"
1319 fi
1320 done
1321}
1322
1323mklinks_abuildrepo() {
1324 [ -n "$REPODEST" ] && return 0
1325 local apk
1326 mkdir -p "$abuildrepo"/$CARCH
1327 cd "$abuildrepo" || return 1
1328 # create links for this package
1329 for apk in $(listpkg); do
1330 [ -f "$PKGDEST"/$apk ] || continue
1331 ln -sf "$PKGDEST"/$apk "$abuildrepo"/$CARCH/$apk
1332 done
1333}
1334
1335build_abuildrepo() {
1336 local d apk _build=build
1337 if ! is_function package; then
1338 # if package() is missing then build is called from rootpkg
1339 _build=true
1340 fi
1341 if ! apk_up2date || [ -n "$force" ]; then
1342 # check early if we have abuild key
1343 abuild-sign --installed || return 1
1344 logcmd "building ${abuildrepo##*/}/$pkgname-$pkgver-r$pkgrel"
1345 sanitycheck && builddeps && clean && fetch && unpack \
1346 && prepare && mkusers && $_build && rootpkg \
1347 && cleanup $CLEANUP \
1348 || return 1
1349 fi
1350 update_abuildrepo_index
1351}
1352
1353update_abuildrepo_index() {
1354 clean_abuildrepo
1355 mklinks_abuildrepo
1356
1357 cd "$abuildrepo"
1358 local index=$CARCH/APKINDEX.tar.gz
1359
1360 msg "Updating the cached abuild repository index..."
1361 local sign=".SIGN.RSA.${SIGN_PUBLIC_KEY##*/}"
1362 local oldindex=
1363 if [ -f "$index" ]; then
1364 oldindex="--index $index"
1365 fi
1366 $APK index --quiet $oldindex --output "$index".unsigned \
1367 --description "$repo $(cd $startdir && git describe)" \
1368 --rewrite-arch $CARCH \
1369 $CARCH/*.apk || exit 1
1370 msg "Signing the index..."
1371 abuild-sign -q "$index".unsigned || exit 1
1372 mv "$index".unsigned "$index"
1373 chmod 644 "$index"
1374}
1375
1376# predefined splitfunc doc
1377default_doc() {
1378 depends="$depends_doc"
1379 pkgdesc="$pkgdesc (documentation)"
1380 arch=${arch_doc:-"noarch"}
1381
1382 local i
1383 for i in doc man info html sgml licenses gtk-doc ri help; do
1384 if [ -d "$pkgdir/usr/share/$i" ]; then
1385 mkdir -p "$subpkgdir/usr/share"
1386 mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/"
1387 fi
1388 done
1389
1390 # compress man pages
1391 find "$subpkgdir"/usr/share/man/*[1-9] \
1392 -type f \! -name \*.gz \! -name \*.bz2 2>/dev/null |
1393 xargs -r gzip -9
1394
1395 rm -f "$subpkgdir/usr/share/info/dir"
1396
1397 # remove if empty, ignore error (not empty)
1398 rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null
1399
1400 return 0
1401}
1402
1403doc() {
1404 default_doc
1405}
1406
1407# predefined splitfunc doc
1408default_dbg() {
1409 local f
1410 binfiles=$(scanelf -R "$pkgdir" | grep ET_DYN | sed "s:$pkgdir\/::g" | sed "s:ET_DYN ::g")
1411 for f in $binfiles; do
1412 srcdir=$(dirname $pkgdir/$f)
1413 srcfile=$(basename $pkgdir/$f)
1414 dstdir=$(dirname $subpkgdir/usr/lib/debug/$f.debug)
1415 dstfile=$(basename $subpkgdir/usr/lib/debug/$f.debug)
1416 if [ ! -d $dstdir ] ; then
1417 mkdir -p $dstdir
1418 fi
1419 cd $srcdir
1420 objcopy --only-keep-debug $srcfile $dstfile
1421 objcopy --add-gnu-debuglink=$dstfile $srcdir/$srcfile
1422 mv $dstfile $dstdir
1423 strip $srcfile
1424 done
1425 return 0
1426}
1427
1428dbg() {
1429 default_dbg
1430}
1431
1432# predefined splitfunc dev
1433default_dev() {
1434 local i= j=
1435 depends="$depends_dev"
1436 pkgdesc="$pkgdesc (development files)"
1437
1438 cd "$pkgdir" || return 0
1439 local libdirs=usr/
1440 [ -d lib/ ] && libdirs="lib/ $libdirs"
1441 for i in usr/include usr/lib/pkgconfig usr/share/aclocal\
1442 usr/share/gettext usr/bin/*-config \
1443 usr/share/vala/vapi usr/share/gir-[0-9]*\
1444 usr/share/qt*/mkspecs \
1445 usr/lib/qt*/mkspecs \
1446 usr/lib/cmake \
1447 $(find . -name include -type d) \
1448 $(find $libdirs -name '*.[acho]' \
1449 -o -name '*.prl' 2>/dev/null); do
1450 if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
1451 d="$subpkgdir/${i%/*}" # dirname $i
1452 mkdir -p "$d"
1453 mv "$pkgdir/$i" "$d"
1454 rmdir "$pkgdir/${i%/*}" 2>/dev/null
1455 fi
1456 done
1457 # move *.so links needed when linking the apps to -dev packages
1458 for i in lib/*.so usr/lib/*.so; do
1459 if [ -L "$i" ]; then
1460 mkdir -p "$subpkgdir"/"${i%/*}"
1461 mv "$i" "$subpkgdir/$i" || return 1
1462 fi
1463 done
1464 return 0
1465}
1466
1467dev() {
1468 default_dev
1469}
1470
1471# predefined splitfunc libs
1472default_libs() {
1473 pkgdesc="$pkgdesc (libraries)"
1474 local dir= file=
1475 for dir in lib usr/lib; do
1476 for file in "$pkgdir"/$dir/lib*.so.[0-9]*; do
1477 [ -f "$file" ] || continue
1478 mkdir -p "$subpkgdir"/$dir
1479 mv "$file" "$subpkgdir"/$dir/
1480 done
1481 done
1482}
1483
1484libs() {
1485 default_libs
1486}
1487
1488is_function() {
1489 type "$1" 2>&1 | head -n 1 | egrep -q "is a (shell )?function"
1490}
1491
1492do_fakeroot() {
1493 if [ -n "$FAKEROOT" ]; then
1494 $FAKEROOT -- "$@"
1495 else
1496 "$@"
1497 fi
1498}
1499
1500# build and package in fakeroot
1501rootpkg() {
1502 local _package=package
1503 if ! is_function package; then
1504 # if package() is missing then run 'build' in fakeroot instead
1505 warning "No package() function in APKBUILD"
1506 _package=build
1507 fi
1508 cd "$startdir"
1509 rm -rf "$pkgdir"
1510 [ -n "$FAKEROOT" ] && msg "Entering fakeroot..."
1511 do_fakeroot "$abuild_path" $color_opt \
1512 $_package \
1513 prepare_subpackages \
1514 prepare_language_packs \
1515 prepare_package \
1516 create_apks
1517}
1518
1519srcpkg() {
1520 getpkgver || return 1
1521 local p="$pkgname-$pkgver-$pkgrel"
1522 local prefix="${startdir##*/}"
1523 local i files="$prefix/APKBUILD"
1524 for i in $source; do
1525 files="$files $prefix/$(filename_from uri $i)"
1526 done
1527 mkdir -p "$PKGDEST"
1528 msg "Creating source package $p.src.tar.gz..."
1529 (cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files)
1530}
1531
1532# return true if arch is supported or noarch
1533check_arch() {
1534 list_has $CARCH $arch || [ "$arch" = "noarch" ] || [ "$arch" = "all" ]
1535}
1536
1537# return true if libc is not masked in options
1538check_libc() {
1539 ! list_has "!libc_$CLIBC" $options
1540}
1541
1542# check if package is up to date
1543apk_up2date() {
1544 getpkgver || return 1
1545 local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk"
1546 local i s
1547 cd "$startdir"
1548 for i in $pkgname $subpackages; do
1549 [ -f "$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" ] || return 1
1550 done
1551 [ -n "$keep" ] && return 0
1552
1553 for i in $source APKBUILD; do
1554 local s
1555 if is_remote "$i"; then
1556 s="$SRCDEST/$(filename_from_uri $i)"
1557 else
1558 s="$startdir/${i##*/}"
1559 fi
1560 if [ "$s" -nt "$pkg" ]; then
1561 return 1
1562 fi
1563 done
1564 return 0
1565}
1566
1567abuildindex_up2date() {
1568 local i
1569 getpkgver || return 1
1570 local dir="$abuildrepo"/$CARCH
1571 local apk="${pkgname%:*}-$pkgver-r$pkgrel.apk"
1572 local idx="$dir"/APKINDEX.tar.gz
1573 local file="$dir"/$apk
1574
1575 # check if index is missing
1576 [ -f "$idx" ] || return 1
1577
1578 # if link or file is missing, then we need update abuildrepo index
1579 [ -f "$file" ] || return 1
1580
1581 # if file exists and is newer than index, then we need update index
1582 [ "$file" -nt "$idx" ] && return 1
1583
1584 return 0
1585}
1586
1587up2date() {
1588 check_arch || return 0
1589 check_libc || return 0
1590 apk_up2date && abuildindex_up2date
1591}
1592
1593# rebuild package and abuildrepo index if needed
1594abuildindex() {
1595 up2date && return 0
1596 build_abuildrepo
1597}
1598
1599# source all APKBUILDs and output:
1600# 1) origin of package
1601# 2) all dependencies
1602# the output is i in a format easy parseable for awk
1603parse_aports_makedepends() {
1604 # lets run this in a subshell since we source all APKBUILD here
1605 (
1606 aportsdir=$(realpath ${APKBUILD%/APKBUILD}/..)
1607 for i in $aportsdir/*/APKBUILD; do
1608 # no forks in this loop or it will be painfully slow!
1609 pkgname=
1610 subpackages=
1611 depends=
1612 makedepends=
1613 . $i
1614 dir=${i%/APKBUILD}
1615 deps=
1616 # filter out conflicts from deps and version info
1617 for j in $depends $makedepends; do
1618 case "$j" in
1619 !*) continue;;
1620 esac
1621 deps="$deps ${j%%[<>=]*}"
1622 done
1623 for j in $pkgname $subpackages; do
1624 echo "o ${j%%:*} $dir"
1625 set -- $deps
1626 echo -n "d ${j%%:*} $1"
1627 shift
1628 while [ $# -gt 0 ]; do
1629 echo -n ",$1"
1630 shift
1631 done
1632 echo
1633 done
1634 done
1635 )
1636}
1637
1638trace_makedepends() {
1639 local deps= i=
1640 # strip versions from deps
1641 for i in "$@"; do
1642 deps="$deps ${i%%[<>=]*}"
1643 done
1644 [ -z "$deps" ] && return 0
1645 ( parse_aports_makedepends
1646 if [ -z "$upgrade" ]; then
1647 # list installed pkgs and prefix with 'i '
1648 $APK info --quiet | sort | sed 's/^/i /'
1649 fi
1650 ) | awk -v pkgs="$deps" '
1651
1652 function depgraph(pkg, a, i) {
1653 if (visited[pkg])
1654 return 0;
1655 visited[pkg] = 1;
1656 split(deps[pkg], a, ",");
1657 for (i in a)
1658 depgraph(a[i]);
1659 print pkg ":" origin[pkg];
1660
1661 }
1662
1663 $1 == "i" { visited[$2] = 1 }
1664 $1 == "o" { origin[$2] = $3 }
1665 $1 == "d" { deps[$2] = $3 }
1666 END {
1667 split(pkgs, pkgarray);
1668 for (i in pkgarray)
1669 depgraph(pkgarray[i]);
1670 }
1671 '
1672}
1673
1674# build and install dependencies
1675builddeps() {
1676 local pkg= i= missing=
1677 local hostdeps= builddeps= installed_hostdeps= installed_builddeps=
1678 [ -n "$nodeps" ] && return 0
1679 msg "Analyzing dependencies..."
1680
1681 # add depends unless it is a subpackage or package itself
1682 if cross_compiling && [ -n "$makedepends_build" -o -n "$makedepends_host" ]; then
1683 builddeps="$makedepends_build"
1684 for i in $BUILD_BASE; do
1685 [ "$pkgname" = "${i%%[<>=]*}" ] && continue
1686 subpackages_has ${i%%[<>=]*} || builddeps="$builddeps $i"
1687 done
1688 hostdeps="$makedepends_host"
1689 for i in $depends; do
1690 [ "$pkgname" = "${i%%[<>=]*}" ] && continue
1691 subpackages_has ${i%%[<>=]*} || hostdeps="$hostdeps $i"
1692 done
1693 else
1694 builddeps="$makedepends"
1695 for i in $BUILD_BASE $depends; do
1696 [ "$pkgname" = "${i%%[<>=]*}" ] && continue
1697 subpackages_has ${i%%[<>=]*} || builddeps="$builddeps $i"
1698 done
1699 fi
1700
1701 installed_builddeps=$($APK info --installed $builddeps)
1702 [ -n "$hostdeps" ] && installed_hostdeps=$($APK info --root "$CBUILDROOT" --installed $hostdeps)
1703
1704 # find which deps are missing
1705 for i in $builddeps; do
1706 if [ "${i#\!}" != "$i" ] && $APK info --quiet --installed "${i#\!}"; then
1707 error "Conflicting package installed: ${i#\!}"
1708 elif ! deplist_has $i $installed_builddeps || [ -n "$upgrade" ]; then
1709 missing="$missing $i"
1710 fi
1711 done
1712 for i in $hostdeps; do
1713 if [ "${i#\!}" != "$i" ] && $APK info --quiet --installed --root "$CBUILDROOT" "${i#\!}"; then
1714 error "Conflicting package installed: ${i#\!}"
1715 elif ! deplist_has $i $installed_hostdeps || [ -n "$upgrade" ]; then
1716 missing="$missing $i"
1717 fi
1718 done
1719
1720 if [ -z "$install_deps" ] && [ -z "$recursive" ]; then
1721 # if we dont have any missing deps we are done now
1722 [ -z "$missing" ] && return 0
1723 error "Missing dependencies: $missing Use -r to autoinstall or -R to build"
1724 return 1
1725 fi
1726
1727 uninstall_after=".makedepends-$pkgname $uninstall_after"
1728 if [ -n "$install_deps" ] && [ -z "$recursive" ]; then
1729 # make a --simulate run first to detect missing deps
1730 # apk-tools --virtual is no goot at reporting those.
1731 $SUDO_APK add --repository "$abuildrepo" $apk_opt_wait \
1732 --simulate --quiet $builddeps || return 1
1733 $SUDO_APK add --repository "$abuildrepo" $apk_opt_wait \
1734 --virtual .makedepends-$pkgname $builddeps || return 1
1735 if [ -n "$hostdeps" ]; then
1736 $SUDO_APK add --root "$CBUILDROOT" --repository "$abuildrepo" $apk_opt_wait \
1737 --simulate --quiet $hostdeps || return 1
1738 $SUDO_APK add --root "$CBUILDROOT" --repository "$abuildrepo" $apk_opt_wait \
1739 --virtual .makedepends-$pkgname $hostdeps || return 1
1740 fi
1741 return 0
1742 fi
1743
1744 if [ -n "$CBUILDROOT" ]; then
1745 error "Recursive rebuilding is not supported when cross compiling."
1746 return 1
1747 fi
1748 [ -z "$recursive" ] && return 1
1749
1750 # find dependencies that are installed but missing in repo.
1751 for i in $builddeps; do
1752 local m=$($APK search --repository "$abuildrepo" ${i%%[<>=]*})
1753 if [ -z "$m" ]; then
1754 missing="$missing $i"
1755 fi
1756 done
1757
1758 for i in $(trace_makedepends $missing); do
1759 # i = pkg:dir
1760 local dir=${i#*:}
1761 local pkg=${i%:*}
1762
1763 # ignore if dependency is in other repo
1764 [ -d "$dir" ] || continue
1765
1766 # check if dep is blacklisted
1767 if list_has $pkg $ABUILD_BLACKLIST; then
1768 error "$pkg is blacklisted"
1769 return 1
1770 fi
1771
1772 # break circular deps
1773 list_has $pkg $ABUILD_VISITED && continue
1774 export ABUILD_VISITED="$ABUILD_VISITED $pkg"
1775
1776 msg "Entering $dir"
1777 cd "$dir" && $0 $forceroot $keep $quiet $install_deps \
1778 $recursive $upgrade $color_opt abuildindex || return 1
1779 done
1780 $SUDO_APK add --upgrade --repository "$abuildrepo" \
1781 $apk_opt_wait \
1782 --virtual .makedepends-$pkgname $builddeps
1783}
1784
1785# replace the md5sums in the APKBUILD
1786checksum() {
1787 local s files
1788 [ -z "$source" ] && [ -n "${md5sums}${sha256sums}${sha512sums}" ] \
1789 && msg "Removing checksums from APKBUILD"
1790 sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
1791 sed -i -e '/^sha512sums="/,/"\$/d; /^sha512sums=''/,/''\$/d' "$APKBUILD"
1792 sed -i -e '/^sha256sums="/,/"\$/d; /^sha256sums=''/,/''\$/d' "$APKBUILD"
1793 [ -z "$source" ] && return 0
1794 fetch
1795 for s in $source; do
1796 files="$files $(filename_from_uri $s)"
1797 done
1798
1799 # for compatibility/backporting reasons we still add md5sum
1800 msg "Updating the md5sums in APKBUILD..."
1801 md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
1802 echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
1803
1804 msg "Updating the sha256sums in APKBUILD..."
1805 sha256sums="$(cd "$srcdir" && sha256sum $files)" \
1806 || die "sha256sum failed"
1807 echo "sha256sums=\"$sha256sums\"" >>"$APKBUILD"
1808
1809 msg "Updating the sha512sums in APKBUILD..."
1810 sha512sums="$(cd "$srcdir" && sha512sum $files)" \
1811 || die "sha512sum failed"
1812 echo "sha512sums=\"$sha512sums\"" >>"$APKBUILD"
1813}
1814
1815stripbin() {
1816 local bin
1817 if options_has "!strip" || [ "$arch" = "noarch" ]; then
1818 return 0
1819 fi
1820 cd "${subpkgdir:-$pkgdir}" || return 1
1821 msg "Stripping binaries"
1822 scanelf --recursive --nobanner --etype "ET_DYN,ET_EXEC" . \
1823 | sed -e 's:^ET_DYN ::' -e 's:^ET_EXEC ::' \
1824 | while read filename; do
1825 XATTR=$(getfattr --match="*" --dump "${filename}")
1826 ${CROSS_COMPILE}strip "${filename}"
1827 [ -n "$XATTR" ] && (echo "$XATTR" | setfattr --restore=-)
1828 done
1829}
1830
1831# simply list target apks
1832listpkg() {
1833 local name
1834 getpkgver || return 1
1835 for name in $(listpkgnames) ; do
1836 echo "$name-$pkgver-r$pkgrel.apk"
1837 done
1838}
1839
1840source_has() {
1841 local i
1842 for i in $source; do
1843 [ "$1" = "${i##*/}" ] && return 0
1844 [ "$1" = "${i%%::*}" ] && return 0
1845 done
1846 return 1
1847}
1848
1849subpackages_has() {
1850 local i
1851 for i in $subpackages; do
1852 [ "$1" = "${i%:*}" ] && return 0
1853 done
1854 return 1
1855}
1856
1857subpackage_types_has() {
1858 local i
1859 for i in $subpackages; do
1860 [ "$1" = "${i##*-}" ] && return 0
1861 done
1862 return 1
1863}
1864
1865list_has() {
1866 local needle="$1"
1867 local i
1868 shift
1869 for i in $@; do
1870 [ "$needle" = "$i" ] && return 0
1871 [ "$needle" = "!$i" ] && return 1
1872 done
1873 return 1
1874}
1875
1876# same as list_has but we filter version info
1877deplist_has() {
1878 local needle="$1"
1879 local i
1880 shift
1881 for i in $@; do
1882 i=${i%%[<>=]*}
1883 [ "$needle" = "$i" ] && return 0
1884 [ "$needle" = "!$i" ] && return 1
1885 done
1886 return 1
1887}
1888
1889options_has() {
1890 list_has "$1" $options
1891}
1892
1893depends_has() {
1894 deplist_has "$1" $depends
1895}
1896
1897makedepends_has() {
1898 deplist_has "$1" $makedepends
1899}
1900
1901md5sums_has() {
1902 list_has "$1" $md5sums
1903}
1904
1905install_has() {
1906 list_has "$1" $install
1907}
1908
1909# install package after build
1910post_add() {
1911 getpkgver || return 1
1912 local pkgf="$PKGDEST/$1-$pkgver-r$pkgrel.apk"
1913 local deps i
1914 if ! subpackages_has $1 && [ "$1" != "$pkgname" ]; then
1915 die "$1 is not built by this APKBUILD"
1916 fi
1917 # recursively install dependencies that are provided by this APKBUILD
1918 deps=$($APK index "$pkgf" 2>/dev/null | awk -F: '$1=="D" { print $2 }')
1919 for i in $deps; do
1920 if subpackages_has $i || [ "$i" = "$pkgname" ]; then
1921 post_add $i || return 1
1922 fi
1923 done
1924 $SUDO_APK add $apk_opt_wait --upgrade "$pkgf" \
1925 || die "Failed to install $1"
1926}
1927
1928deps() {
1929 local builddeps i
1930 builddeps="$makedepends"
1931 for i in $depends; do
1932 [ "$pkgname" = "${i%%[<>=]*}" ] && continue
1933 subpackages_has ${i%%[<>=]*} || builddeps="$builddeps $i"
1934 done
1935 $SUDO_APK add $apk_opt_wait --repository "$abuildrepo" \
1936 --virtual .makedepends-$pkgname \
1937 $builddeps
1938}
1939
1940undeps (){
1941 $SUDO_APK del $apk_opt_wait .makedepends-$pkgname
1942 if cross_compiling; then
1943 $SUDO_APK del --root "$CBUILDROOT" $apk_opt_wait \
1944 .makedepends-$pkgname
1945 fi
1946}
1947
1948# compat
1949installdeps() { deps; }
1950uninstalldeps() { undeps; }
1951index() { update_abuildrepo_index; }
1952
1953all() {
1954 if ! [ -n "$force" ]; then
1955 check_arch
1956 if [ $? -ne 0 ]; then
1957 echo "Package not available for the target architecture ($CARCH). Aborting."
1958 return 0
1959 fi
1960 check_libc || return 0
1961 fi
1962 if up2date && [ -z "$force" ]; then
1963 msg "Package is up to date"
1964 else
1965 build_abuildrepo
1966 fi
1967}
1968
1969# This abuild hook will checkout an svn or git repository by specifying
1970# $svnurl or $giturl in APKBUILD. You can checkout a specific branch in
1971# git by adding -b $branch in $giturl. $reporev will select the correct
1972# commit, revision or tag for you. If you specify $disturl your distfile
1973# will automatically be uploaded with rsync to the url provided.
1974# Base version defaults to 0 except if specified by $verbase.
1975
1976snapshot() {
1977 # check if we setup vars correctly
1978 [ -z "$disturl" ] && warning "Missing disturl in APKBUILD, auto uploading disabled."
1979 [ -z "$svnurl" ] && [ -z "$giturl" ] && die "Missding repository url in APKBUILD!"
1980 [ -n "$svnurl" ] && [ -n "$giturl" ] && die "You can only use a single repository!"
1981 local _date=$(date +%Y%m%d)
1982 local _format="tar.gz"
1983 # remove any repositories left in srcdir
1984 abuild clean
1985 mkdir -p "$srcdir" && cd "$srcdir"
1986 # clone git repo and archive
1987 if [ -n "$giturl" ]; then
1988 local _version=${verbase:-0}_git${_date}
1989 command -v git >/dev/null || \
1990 die "Missing git! Install git to support git clone."
1991 [ -z "$reporev" ] && local _rev="HEAD" && local _depth="--depth=1"
1992 msg "Creating git snapshot: $pkgname-$_version"
1993 git clone $_depth --bare $giturl $pkgname-$_version || return 1
1994 git --git-dir $pkgname-$_version archive \
1995 --format=$_format \
1996 -o $pkgname-$_version.$_format \
1997 --prefix=$pkgname-$_version/ $_rev \
1998 || return 1
1999 fi
2000 # export svn repo and archive
2001 if [ -n "$svnurl" ]; then
2002 local _version=${verbase:-0}_svn${_date}
2003 command -v svn >/dev/null || \
2004 die "Missing svn! Install subverion to support svn export."
2005 [ -n "$reporev" ] && local _rev="-r $reporev"
2006 msg "Creating svn snapshot: $pkgname-$_version"
2007 svn co $_rev $svnurl $pkgname-$_version || return 1
2008 tar zcf $pkgname-$_version.$_format $pkgname-$_version || return 1
2009 fi
2010 # upload to defined distfiles url
2011 if [ -n "$disturl" ]; then
2012 command -v rsync >/dev/null || \
2013 die "Missing rsync! Install rsync to enable automatic uploads."
2014 msg "Uploading to $disturl"
2015 rsync --progress -La $pkgname-$_version.$_format \
2016 $disturl || return 1
2017 cd "$startdir"
2018 # set the pkgver to current date and update checksum
2019 sed -i -e "s/^pkgver=.*/pkgver=${_version}/" \
2020 APKBUILD || return 1
2021 abuild checksum
2022 fi
2023}
2024
2025usage() {
2026 echo "$program $program_version"
2027 cat << EOF
2028usage: $program [options] [-i PKG] [-P REPODEST] [-p PKGDEST]
2029 [-s SRCDEST] [cmd] ...
2030 $program [-c] -n PKGNAME[-PKGVER]
2031Options:
2032 -A Print CARCH and exit
2033 -c Enable colored output
2034 -d Disable dependency checking
2035 -f Force specified cmd, even if they are already done
2036 -F Force run as root
2037 -h Show this help
2038 -i Install PKG after successful build
2039 -k Keep built packages, even if APKBUILD or sources are newer
2040 -m Disable colors (monochrome)
2041 -p Set package destination directory
2042 -P Set PKGDEST to REPODEST/<repo>/\$CARCH, where repo is the parents dir name
2043 -q Quiet
2044 -r Install missing dependencies from system repository (using sudo)
2045 -R Recursively build and install missing dependencies (using sudo)
2046 -s Set source package destination directory
2047 -u Recursively build and upgrade all dependencies (using sudo)
2048
2049Commands:
2050 build Compile and install package into \$pkgdir
2051 checksum Generate checksum to be included in APKBUILD
2052 clean Remove temp build and install dirs
2053 cleancache Remove downloaded files from \$SRCDEST
2054 cleanoldpkg Remove binary packages except current version
2055 cleanpkg Remove already built binary and source package
2056 deps Install packages listed in makedepends and depends
2057 fetch Fetch sources to \$SRCDEST and verify checksums
2058 index Regenerate the APKINDEX for abuildrepo
2059 listpkg List target packages
2060 package Create package in \$PKGDEST
2061 prepare Apply patches
2062 rootpkg Run 'package', the split functions and create apks as fakeroot
2063 sanitycheck Basic sanity check of APKBUILD
2064 snapshot Create a \$giturl or \$svnurl snapshot and upload to \$disturl
2065 sourcecheck Check if remote source package exists upstream
2066 srcpkg Make a source package
2067 undeps Uninstall packages listed in makedepends and depends
2068 unpack Unpack sources to \$srcdir
2069 up2date Compare target and sources dates
2070 verify Verify checksums
2071
2072EOF
2073 exit 0
2074}
2075
2076APKBUILD="${APKBUILD:-./APKBUILD}"
2077unset force
2078unset recursive
2079while getopts "AcdfFhi:kimnp:P:qrRs:u" opt; do
2080 case $opt in
2081 'A') echo "$CARCH"; exit 0;;
2082 'c') enable_colors
2083 color_opt="-c";;
2084 'd') nodeps=1;;
2085 'f') force="-f";;
2086 'F') forceroot="-F";;
2087 'h') usage;;
2088 'i') install_after="$install_after $OPTARG";;
2089 'k') keep="-k";;
2090 'm') disable_colors
2091 color_opt="-m";;
2092 'n') die "Use newapkbuild to create new aports";;
2093 'p') PKGDEST=$OPTARG;;
2094 'P') REPODEST=$OPTARG;;
2095 'q') quiet="-q";;
2096 'r') install_deps="-r";;
2097 'R') recursive="-R";;
2098 's') SRCDEST=$OPTARG;;
2099 'u') upgrade="-u"
2100 recursive="-R";;
2101 esac
2102done
2103shift $(( $OPTIND - 1 ))
2104
2105# check so we are not root
2106if [ "$(whoami)" = "root" ] && [ -z "$FAKEROOTKEY" ]; then
2107 [ -z "$forceroot" ] && die "Do not run abuild as root"
2108 FAKEROOT=
2109fi
2110
2111# find startdir
2112[ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
2113APKBUILD=$(readlink -f "$APKBUILD")
2114
2115startdir="${APKBUILD%/*}"
2116srcdir=${srcdir:-"$startdir/src"}
2117pkgbasedir=${pkgbasedir:-"$startdir/pkg"}
2118
2119repo=${startdir%/*}
2120repo=${repo##*/}
2121
2122SRCDEST=${SRCDEST:-$startdir}
2123PKGDEST=${PKGDEST:-$startdir}
2124
2125# set a default CC
2126: ${CC:=gcc}
2127export CC
2128
2129cd "$startdir" || die
2130. "$APKBUILD"
2131
2132# If REPODEST is set then it will override the PKGDEST
2133if [ -n "$REPODEST" ]; then
2134 PKGDEST="$REPODEST/$repo/$CARCH"
2135 # for recursive action
2136 export REPODEST
2137 abuildrepo="$REPODEST"/$repo
2138else
2139 abuildrepo="$abuildrepo_base"/$repo
2140fi
2141
2142# if we want build debug package
2143if [ -n "$DEBUG" ] || subpackage_types_has "dbg"; then
2144 CFLAGS="$CFLAGS -g"
2145 CXXFLAGS="$CXXFLAGS -g"
2146 options="$options !strip"
2147fi
2148
2149# If we are handling a sub package then reset subpackages and install
2150if [ -n "$subpkgname" ]; then
2151 origsubpackages="$subpackages"
2152 subpackages=
2153fi
2154pkgdir="$pkgbasedir/$pkgname"
2155controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname}
2156
2157trap 'die "Aborted by user"' INT
2158set_xterm_title "abuild: $pkgname"
2159
2160if [ -z "$1" ]; then
2161 set all
2162fi
2163
2164while [ $# -gt 0 ]; do
2165 runpart $1
2166 shift
2167done
2168
2169for i in $install_after; do
2170 post_add $i
2171done
2172
2173cleanup
2174