projects/aports·blob v2.28.0 · refs

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