projects/aports·blob v2.27.0 · refs

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