projects/aports·blob v2.29.0 · refs

2290 lines · 56.0 KiB

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