projects/aports·blob v2.27.2 · refs

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