projects/aports·blob v2.0_rc8 · refs

1079 lines · 24.9 KiB

1#!/bin/sh
2
3# script to build apk packages (light version of makepkg)
4# Copyright (c) 2008 Natanael Copa <[email protected]>
5#
6# Distributed under GPL-2
7#
8# Depends on: busybox utilities, fakeroot,
9#
10
11abuild_ver=@VERSION@
12sysconfdir=@sysconfdir@
13apkcache=@apkcache@
14
15startdir="$PWD"
16srcdir=${srcdir:-"$startdir/src"}
17pkgbasedir=${pkgbasedir:-"$startdir/pkg"}
18pkgrel=0
19repo=${startdir%/*}
20repo=${repo##*/}
21
22# defaults
23SRCDEST=${SRCDEST:-$startdir}
24PKGDEST=${PKGDEST:-$startdir}
25BUILD_BASE="build-base"
26
27SUDO=${SUDO:-"sudo"}
28
29default_cmds="sanitycheck builddeps clean fetch unpack mkusers rootpkg apkcache"
30
31# read config
32ABUILD_CONF=${ABUILD_CONF:-"$sysconfdir/abuild.conf"}
33[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"
34
35# source functions
36datadir=/usr/share/abuild
37
38#colors
39if [ -n "$USE_COLORS" ]; then
40 NORMAL="\033[1;0m"
41 STRONG="\033[1;1m"
42 RED="\033[1;31m"
43 GREEN="\033[1;32m"
44 YELLOW="\033[1;33m"
45 BLUE="\033[1;34m"
46fi
47
48
49# functions
50msg() {
51 local prompt="$GREEN>>>${NORMAL}"
52 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
53 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
54 [ -z "$quiet" ] && printf "${prompt} ${name}${fake}: $@\n" >&2
55}
56
57warning() {
58 local prompt="${YELLOW}>>> WARNING:${NORMAL}"
59 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
60 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
61 printf "${prompt} ${name}${fake}: $@\n" >&2
62}
63
64error() {
65 local prompt="${RED}>>> ERROR:${NORMAL}"
66 local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
67 local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
68 printf "${prompt} ${name}${fake}: $@\n" >&2
69}
70
71
72set_xterm_title() {
73 if [ "$TERM" = xterm ]; then
74 printf "\033]0;$1\007" >&2
75 fi
76}
77
78cleanup() {
79 set_xterm_title ""
80 if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then
81 $SUDO apk del $uninstall_after
82 fi
83}
84
85die() {
86 error "$@"
87 cleanup
88 exit 1
89}
90
91# check if apkbuild is basicly sane
92sanitycheck() {
93 local i
94 msg "Checking sanity of $APKBUILD..."
95 [ -z "$pkgname" ] && die "Missing pkgname in APKBUILD"
96 [ -z "${pkgname##* *}" ] && die "pkgname contains spaces"
97 [ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
98 if [ "$pkgver" != "volatile" ]; then
99 apk version --check -q "$pkgver" ||\
100 die "$pkgver is not a valid version"
101 fi
102 [ -z "$pkgrel" ] && warning "Missing pkgrel in APKBUILD. Using pkgrel=0"
103 [ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD"
104 [ -z "$url" ] && die "Missing url in APKBUILD"
105 [ -z "$license" ] && die "Missing license in APKBULID"
106
107 for i in $install; do
108 [ -e "$startdir/$i" ] || die "install script $startdir/$i is missing"
109 done
110
111 [ -n "${triggers%%:*}" ] && [ ! -e "$startdir"/${triggers%%:*} ] \
112 && die "trigger script $startdir/${triggers%%:*} is missing"
113
114 if [ -n "$source" ]; then
115 for i in $source; do
116 if install_has "$i"; then
117 warning "You should not have \$install in source"
118 continue
119 fi
120 md5sums_has ${i##*/} || die "${i##*/} is missing in md5sums"
121 case "$i" in
122 https://*) makedepends_has wget || die "wget must be in makedepends when source has https://" ;;
123 esac
124 done
125 fi
126
127 if [ -n "$md5sums" ]; then
128 for i in $(echo "$md5sums" | awk '{ print $2 }'); do
129 source_has $i || die "$i exists in md5sums but is missing in source"
130 done
131 fi
132
133 # common spelling errors
134 [ -n "$depend" ] && die "APKBUILD contains 'depend'. It should be depends"
135 [ -n "$makedepend" ] && die "APKBUILD contains 'makedepend'. It should be makedepends"
136
137 grep '^# Maintainer:' $APKBUILD >/dev/null || warning "No maintainer"
138
139 makedepends_has 'g++' && warning "g++ should not be in makedepends"
140 return 0
141}
142
143md5check() {
144 local dummy f
145 if [ -z "$source" ]; then
146 return 0
147 fi
148 if [ -z "$md5sums" ]; then
149 die "Use 'abuild checksum' to generate/update the checksum(s)"
150 fi
151 if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
152 die "Number of md5sums does not correspond to number of sources"
153 fi
154 fetch || return 1
155 msg "Checking md5sums..."
156 cd "$srcdir" && echo "$md5sums" | md5sum -c
157}
158
159uri_fetch() {
160 local uri="$1"
161 local d="${s##*/}" # $(basename $s)
162 local opts
163 [ -n "$quiet" ] && opts="-q"
164 [ -f "$SRCDEST/$d" ] && return 0
165
166
167 # we need GNU wget for this
168 case "$uri" in
169 https://*) opts="--no-check-certificate";;
170 esac
171
172 mkdir -p "$SRCDEST"
173 if [ -f "$SRCDEST/$d.part" ]; then
174 msg "Partial download found. Trying to resume"
175 opts="$opts -c"
176 fi
177 msg "Fetching $uri"
178 wget $opts -O "$SRCDEST/$d.part" "$uri" \
179 && mv "$SRCDEST/$d.part" "$SRCDEST/$d"
180}
181
182is_remote() {
183 case "$1" in
184 http://*|ftp://*|https://*)
185 return 0;;
186 esac
187 return 1
188}
189
190fetch() {
191 local s
192 mkdir -p "$srcdir"
193 for s in $source; do
194 if is_remote "$s"; then
195 uri_fetch "$s" || return 1
196 ln -sf "$SRCDEST/${s##*/}" "$srcdir"/
197 else
198 ln -sf "$startdir/$s" "$srcdir/"
199 fi
200 done
201}
202
203# unpack the sources
204unpack() {
205 local u
206 md5check || return 1
207 mkdir -p "$srcdir"
208 for u in $source; do
209 local s="$SRCDEST/${u##*/}" # $(basename $s)
210 case "$s" in
211 *.tar.gz|*.tgz)
212 msg "Unpacking $s..."
213 tar -C "$srcdir" -zxf "$s" || return 1;;
214 *.tar.bz2)
215 msg "Unpacking $s..."
216 tar -C "$srcdir" -jxf "$s" || return 1;;
217 *.tar.lzma)
218 msg "Unpacking $s..."
219 unlzma -c "$s" | tar -C "$srcdir" -x \
220 || return 1;;
221 *.zip)
222 msg "Unpacking $s..."
223 unzip "$s" -d "$srcdir" || return 1;;
224 esac
225 done
226}
227
228# cleanup source and package dir
229clean() {
230 msg "Cleaning temporary build dirs..."
231 rm -rf "$srcdir"
232 rm -rf "$pkgbasedir"
233}
234
235# cleanup fetched sources
236cleancache() {
237 local s
238 for s in $source; do
239 if is_remote "$s"; then
240 msg "Cleaning downloaded ${s##*/}..."
241 rm -f "$SRCDEST/${s##*/}"
242 fi
243 done
244}
245
246cleanpkg() {
247 local i
248 msg "Cleaning built packages..."
249 for i in $pkgname $subpackages; do
250 local p="${i%:*}-$pkgver-r$pkgrel"
251 rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz" \
252 "$apkcache"/$p.apk
253 done
254 # remove given packages from index
255}
256
257# clean all packages except current
258cleanoldpkg() {
259 local i j
260 msg "Cleaning all packages except $pkgver-r$pkgrel..."
261 for i in $pkgname $subpackages; do
262 for j in "$PKGDEST"/${i%:*}-[0-9]*.apk; do
263 [ "$j" != "$PKGDEST/${i%:*}-$pkgver-r$pkgrel.apk" ] \
264 && rm -f "$j"
265 done
266 done
267 return 0
268}
269
270mkusers() {
271 local i
272 for i in $pkgusers; do
273 if ! getent passwd $i >/dev/null; then
274 msg "Creating user $i"
275 $SUDO adduser -D -H $i || return 1
276 fi
277 done
278 for i in $pkggroups; do
279 if ! getent group $i >/dev/null; then
280 msg "Creating group $i"
281 $SUDO addgroup $i || return 1
282 fi
283 done
284}
285
286
287runpart() {
288 local part=$1
289 [ -n "$DEBUG" ] && msg "$part"
290 $part || die "$part failed"
291}
292
293# override those in your build script
294build() {
295 die "No build() function found in $APKBUILD"
296}
297
298get_split_func() {
299 # get the 'func' from "sub-pkg:func"
300 local func=${1##*:}
301
302 # get 'func' from "sub-pkg-func" if there was no :func
303 [ "$func" = "$1" ] && func=${func##*-}
304 echo $func
305}
306
307prepare_subpackages() {
308 if [ -z "$subpackages" ]; then
309 return 0
310 fi
311 local i
312 cd "$startdir"
313 for i in $subpackages; do
314 local func=$(get_split_func $i)
315 # call abuild recursively, setting subpkg{dir,name}
316 msg "Running split function $func..."
317 subpkgdir="$pkgbasedir/${i%:*}" subpkgname="${i%:*}" \
318 $0 $func prepare_package || return 1
319 done
320}
321
322prepare_metafiles() {
323 local name=${subpkgname:-$pkgname}
324 [ -z "${name##* *}" ] && die "package name contains spaces"
325 local dir=${subpkgdir:-$pkgdir}
326 local pkg="$name-$pkgver-r$pkgrel.apk"
327 local pkginfo="$controldir"/.PKGINFO
328 local sub
329
330 [ ! -d "$dir" ] && die "Missing $dir"
331 cd "$dir"
332 mkdir -p "$controldir"
333 local builddate=$(date -u "+%s")
334 local size=$(du -sk | awk '{print $1 * 1024}')
335
336 echo "# Generated by $(basename $0) $abuild_ver" >"$pkginfo"
337 if [ -n "$FAKEROOTKEY" ]; then
338 echo "# using $(fakeroot -v)" >> "$pkginfo"
339 fi
340 echo "# $(date -u)" >> "$pkginfo"
341 cat >> "$pkginfo" <<EOF
342pkgname = $name
343pkgver = $pkgver-r$pkgrel
344pkgdesc = $pkgdesc
345url = $url
346builddate = $builddate
347packager = ${PACKAGER:-"Unknown"}
348size = $size
349EOF
350 local i deps
351 deps="$depends"
352 if [ "$pkgname" != "busybox" ] && ! depends_has busbox; then
353 for i in $install ${triggers%%:*}; do
354 if head -n 1 "$startdir/$i" | grep '^#!/bin/sh' >/dev/null ; then
355 msg "Script found. busybox added as a dependency for $pkg"
356 deps="$deps busybox"
357 break
358 fi
359 done
360 fi
361
362 for i in $license; do
363 echo "license = $i" >> "$pkginfo"
364 done
365 for i in $replaces; do
366 echo "replaces = $i" >> "$pkginfo"
367 done
368 for i in $deps; do
369 echo "depend = $i" >> "$pkginfo"
370 done
371 for i in $conflicts; do
372 echo "conflict = $i" >> "$pkginfo"
373 done
374 for i in $provides; do
375 echo "provides = $i" >> "$pkginfo"
376 done
377 for i in $backup; do
378 echo "backup = $i" >> "$pkginfo"
379 done
380 if [ -n "$triggers" ]; then
381 echo "triggers = ${triggers#*:}" >> "$pkginfo"
382 fi
383
384 local metafiles=".PKGINFO"
385 for i in $install ${triggers%%:*}; do
386 script=${i#$name}
387 case "$script" in
388 .pre-install|.post-install|.pre-upgrade|.post-upgrade|.pre-deinstall|.post-deinstall|.trigger)
389 msg "Adding $script"
390 ;;
391 *) error "$script: Invalid install/trigger script"
392 return 1
393 ;;
394 esac
395 cp "$startdir/$i" "$controldir/$script" || return 1
396 chmod +x "$controldir/$script"
397 metafiles="$metafiles $script"
398 done
399 echo $metafiles | tr ' ' '\n' > "$controldir"/.metafiles
400}
401
402prepare_tracedeps() {
403 local dir=${subpkgdir:-$pkgdir}
404 options_has "!tracedeps" && return 0
405 find -name '*.so' -o -name '*.so.[0-9]*' | sed 's:.*/::' \
406 >"$controldir"/.provides-so
407 scanelf -Rn "$dir" | awk -F "\ " '$1 == "ET_DYN" || $1 == "ET_EXEC" {print $2}' \
408 | sed 's:,:\n:g' | sort | uniq \
409 | while read i; do
410 # only add files that are not self provided
411 grep "^$i$" "$controldir"/.provides-so >/dev/null \
412 || echo $i >> "$controldir"/.needs-so
413 done
414}
415
416prepare_package() {
417 msg "Preparing ${subpkgname:+sub}package ${subpkgname:-$pkgname}..."
418 stripbin
419 prepare_metafiles
420 prepare_tracedeps
421}
422
423pkginfo_val() {
424 local key="$1"
425 local file="$2"
426 awk -F ' = ' "\$1 == \"$key\" {print \$2}" "$file"
427}
428
429trace_apk_deps() {
430 local name="$1"
431 local dir="$2"
432 local i j found autodeps=
433 msg "Tracing dependencies for $name..."
434 for i in $(cat "$dir"/.needs-so 2>/dev/null); do
435 found=
436 # first check if its provide by same apkbuild
437 for j in "$dir"/../.control.*/.provides-so; do
438 grep -w "$i" "$j" >/dev/null || continue
439 found=${j%/.provides-so}
440 found=${found##*/.control.}
441 break
442 done
443 # check apk db if not provided by a subpackage
444 if [ -z "$found" ]; then
445 found=$(apk info -q -W /lib/$i /usr/lib/$i)
446 fi
447 if [ -z "$found" ]; then
448 error "Could not find dependency for $i"
449 return 1
450 fi
451 if grep -w "^depend = ${found}$" "$dir"/.PKGINFO >/dev/null ; then
452 warning "You can remove '$found' from depends"
453 continue
454 fi
455 list_has "$found" $autodeps || autodeps="$autodeps $found"
456 msg "Added '$found' as dependency as it has $i"
457 done
458 [ -z "$autodeps" ] && return 0
459 echo "# automatically detected:" >> "$dir"/.PKGINFO
460 for i in $autodeps; do
461 echo "depend = $i" >> "$dir"/.PKGINFO
462 done
463 # add pkgconfig if usr/lib/pkgconfig is found
464 if [ -d "$pkgbasdir"/$name/usr/lib/pkgconfig ] \
465 && ! grep -q '^depend = pkgconfig' "$dir"/.PKGINFO; then
466 msg "Added pkgconfig as dependency"
467 echo "depend = pkgconfig" >> "$dir"/.PKGINFO
468 fi
469}
470
471create_apks() {
472 local file
473 for file in "$pkgbasedir"/.control.*/.PKGINFO; do
474 local dir="${file%/.PKGINFO}"
475 local name=$(pkginfo_val pkgname $file)
476 local ver=$(pkginfo_val pkgver $file)
477 local apk=$name-$ver.apk
478 local datadir="$pkgbasedir"/$name
479
480 trace_apk_deps "$name" "$dir" || return 1
481 msg "Creating $apk..."
482 (
483 cd "$datadir"
484 # data.tar.gz
485 set -- *
486 if [ "$1" = '*' ]; then
487 touch .dummy
488 set -- .dummy
489 fi
490 tar -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz
491
492 # append the hash for data.tar.gz
493 local sha256=$(sha256sum "$dir"/data.tar.gz | cut -f1 -d' ')
494 echo "datahash = $sha256" >> "$dir"/.PKGINFO
495
496 # control.tar.gz
497 cd "$dir"
498 tar -c $(cat "$dir"/.metafiles) | abuild-tar --cut \
499 | gzip -9 > control.tar.gz
500 abuild-sign -q control.tar.gz || exit 1
501
502 # create the final apk
503 cat control.tar.gz data.tar.gz > "$PKGDEST"/$apk
504 )
505 done
506}
507
508apkcache() {
509 if ! apk_up2date || [ -n "$force" ]; then
510 sanitycheck && builddeps && clean && fetch && unpack \
511 && mkusers && rootpkg || return 1
512 fi
513
514 local apk
515 mkdir -p "$apkcache" || return 1
516 cd "$apkcache"
517
518 # remove broken links
519 for apk in *.apk; do
520 if [ -L "$apk" ] && [ ! -f "$apk" ]; then
521 rm -f "$apk"
522 fi
523 done
524
525 # create links for this package
526 for apk in $(listpkg); do
527 ln -sf "$PKGDEST"/$apk "$apkcache"/$apk
528 done
529
530 msg "Updating the cached abuild repository index..."
531 local sign=".SIGN.RSA.${SIGN_PUBLIC_KEY##*/}"
532 local oldindex=
533 if [ -f APKINDEX.tar.gz ]; then
534 oldindex="--index APKINDEX.tar.gz"
535 fi
536 apk index $oldindex --output APKINDEX.tar.gz.unsigned *.apk || exit 1
537 msg "Signing the index..."
538 abuild-sign -q APKINDEX.tar.gz.unsigned || exit 1
539 mv APKINDEX.tar.gz.unsigned APKINDEX.tar.gz
540 chmod 644 APKINDEX.tar.gz
541}
542
543# predefined splitfunc doc
544default_doc() {
545 depends="$depends_doc"
546 install="$install_doc"
547 triggers="$triggers_doc"
548 local i
549 for i in doc man info html sgml licenses gtk-doc; do
550 if [ -d "$pkgdir/usr/share/$i" ]; then
551 mkdir -p "$subpkgdir/usr/share"
552 mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/"
553 fi
554 done
555
556 rm -f "$subpkgdir/usr/share/info/dir"
557
558# # compress info and man pages
559# find "$subpkgdir/usr/share" \( -name '*.info' -o -name '*.info-[1-9]' \
560# -o -name '*.[1-9]' \) -exec gzip {} \;
561
562 # remove if empty, ignore error (not empty)
563 rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null
564
565# [ -d "$subpkgdir/usr/share/man" ] && depends="man"
566 return 0
567}
568
569doc() {
570 default_doc
571}
572
573# predefined splitfunc mod
574default_mod() {
575 depends="$kernel $depends_mod"
576 install="$install_mod"
577 for i in firmware modules; do
578 if [ -d "$pkgdir/lib/$i" ]; then
579 rm -rf "$subpkgdir/lib"
580 mkdir -p "$subpkgdir/lib"
581 mv "$pkgdir/lib/$i" "$subpkgdir/lib"
582 fi
583 done
584}
585
586mod() {
587 default_mod
588}
589
590# predefined splitfunc dev
591default_dev() {
592 local i
593 depends="$pkgname $depends_dev"
594 install="$install_dev"
595 triggers="$triggers_dev"
596 for i in $origsubpackages; do
597 [ "${i%:*}" = "$subpkgname" ] || depends="$depends ${i%:*}"
598 done
599
600 cd "$pkgdir" || return 0
601 for i in usr/include usr/lib/pkgconfig usr/share/aclocal\
602 usr/share/gettext usr/bin/*-config \
603 $(find -name include -type d) \
604 $(find usr/ -name '*.[acho]' -o -name '*.la' \
605 2>/dev/null); do
606 if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
607 d="$subpkgdir/${i%/*}" # dirname $i
608 mkdir -p "$d"
609 mv "$pkgdir/$i" "$d"
610 rmdir "$pkgdir/${i%/*}" 2>/dev/null
611 fi
612 done
613 return 0
614}
615
616dev() {
617 default_dev
618}
619
620# build and package in fakeroot
621rootpkg() {
622 cd "$startdir"
623 msg "Entering fakeroot..."
624 fakeroot $0 build prepare_subpackages prepare_package create_apks
625}
626
627srcpkg() {
628 local p="$pkgname-$pkgver-$pkgrel"
629 local prefix="${startdir##*/}"
630 local i files="$prefix/APKBUILD"
631 for i in $source; do
632 files="$files $prefix/${i##*/}"
633 done
634 mkdir -p "$PKGDEST"
635 msg "Creating source package $p.src.tar.gz..."
636 (cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files)
637}
638
639# check if package is up to date
640apk_up2date() {
641 local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk"
642 local i s
643 cd "$startdir"
644 for i in $pkgname $subpackages; do
645 [ -f "$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" ] || return 1
646 done
647 [ -n "$keep" ] && return 0
648
649 for i in $source APKBUILD; do
650 local s
651 if is_remote "$i"; then
652 s="$SRCDEST/${i##*/}" # $(basename $i)
653 else
654 s="$startdir/${i##*/}"
655 fi
656 if [ "$s" -nt "$pkg" ]; then
657 return 1
658 fi
659 done
660 return 0
661}
662
663cache_up2date() {
664 local i apk
665 for i in $pkgname $subpackages; do
666 apk="${i%:*}-$pkgver-r$pkgrel.apk"
667 [ "$apkcache"/APKINDEX.tar.gz -nt "$apkcache"/$apk ] || return 1
668 done
669 return 0
670}
671
672up2date() {
673 apk_up2date && cache_up2date
674}
675
676# source all APKBUILDs and output:
677# 1) origin of package
678# 2) all dependencies
679# the output is i in a format easy parseable for awk
680depparse_aports() {
681 # lets run this in a subshell since we source all APKBUILD here
682 (
683 aportsdir=$(realpath ${APKBUILD%/APKBUILD}/../..)
684 for i in $aportsdir/*/*/APKBUILD; do
685 pkgname=
686 subpackages=
687 depends=
688 makedepends=
689 . $i
690 dir=${i%/APKBUILD}
691 deps=
692 # filter out conflicts from deps and version info
693 for j in $depends $makedepends; do
694 case "$j" in
695 !*) continue;;
696 esac
697 deps="$deps ${j%[<>=]*}"
698 done
699 for j in $pkgname $subpackages; do
700 echo "o ${j%%:*} $dir"
701 set -- $deps
702 echo -n "d ${j%%:*} $1"
703 shift
704 while [ $# -gt 0 ]; do
705 echo -n ",$1"
706 shift
707 done
708 echo
709 done
710 done
711 )
712}
713
714deptrace() {
715 local deps="$@"
716 [ -z "$deps" ] && return 0
717 ( depparse_aports
718 if [ -z "$upgrade" ]; then
719 # list installed pkgs and prefix with 'i '
720 apk info -q | sort | sed 's/^/i /'
721 fi
722 ) | awk -v pkgs="$deps" '
723
724 function depgraph(pkg, a, i) {
725 if (visited[pkg])
726 return 0;
727 visited[pkg] = 1;
728 split(deps[pkg], a, ",");
729 for (i in a)
730 depgraph(a[i]);
731 print pkg ":" origin[pkg];
732
733 }
734
735 $1 == "i" { visited[$2] = 1 }
736 $1 == "o" { origin[$2] = $3 }
737 $1 == "d" { deps[$2] = $3 }
738 END {
739 split(pkgs, pkgarray);
740 for (i in pkgarray)
741 depgraph(pkgarray[i]);
742 }
743 '
744}
745
746# build and install dependencies
747builddeps() {
748 local deps= alldeps= pkg= i= dir= ver= missing= installed_deps=
749 local filtered_deps=
750 [ -n "$nodeps" ] && return 0
751 msg "Analyzing dependencies..."
752 deps="$BUILD_BASE $makedepends"
753
754 # add depends unless it is a subpackage
755 for i in $depends; do
756 subpackages_has ${i%[<>=]*} || deps="$deps $i"
757 done
758
759 installed_deps=$(apk info -e $deps)
760 # find which deps are missing
761 for i in $deps; do
762 if [ "${i#\!}" != "$i" ]; then
763 list_has ${i#\!} $installed_deps \
764 && die "Conflicting package ${i#\!} is installed."
765 elif ! deplist_has $i $installed_deps; then
766 if [ -z "$install_deps" ] && [ -z "$recursive" ]; then
767 die "Missing dependency $i. Use -r to autoinstall or -R to build"
768 fi
769 missing="$missing $i"
770 fi
771 done
772
773 [ -z "$missing" ] && [ -z "$install_deps" ] && [ -z "$recursive" ] \
774 && return 0
775
776 uninstall_after=".makedepends-$pkgname $uninstall_after"
777 if [ -n "$install_deps" ] && [ -z "$recursive" ]; then
778 $SUDO apk add --repository "$apkcache" \
779 --virtual .makedepends-$pkgname $deps \
780 && return 0
781 fi
782
783 [ -z "$recursive" ] && return 1
784
785 # find dependencies that are installed but missing in repo.
786 for i in $deps; do
787 local m=$(apk search --repository "$apkcache" ${i%[<>=]*})
788 if [ -z "$m" ]; then
789 missing="$missing $i"
790 fi
791 done
792
793 for i in $(deptrace $missing); do
794 # i = pkg:dir
795 local dir=${i#*:}
796 local pkg=${i%:*}
797 msg "Entering $dir"
798 cd "$dir" && $0 -k -r apkcache || return 1
799 done
800 $SUDO apk add -u --repository "$apkcache" \
801 --virtual .makedepends-$pkgname $deps
802}
803
804# replace the md5sums in the APKBUILD
805checksum() {
806 local s files
807 [ -z "$source" ] && return 0
808 fetch
809 msg "Updating the md5sums in APKBUILD..."
810 for s in $source; do
811 files="$files ${s##*/}"
812 done
813 md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
814 sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
815 echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
816}
817
818stripbin() {
819 local bin
820 options_has "!strip" && return 0
821 cd "${subpkgdir:-$pkgdir}" || return 1
822 msg "Stripping binaries"
823 find . -type f 2>/dev/null | while read bin; do
824 local opt=
825 case "$(file -biz "$bin")" in
826 */x-sharedlib*|*/x-archive*)
827 strip --strip-debug "$bin";;
828 */x-executable*)
829 strip "$bin";;
830 esac
831 done
832 return 0
833}
834
835# simply list target apks
836listpkg() {
837 local i
838 for i in $pkgname $subpackages; do
839 echo "${i%:*}-$pkgver-r$pkgrel.apk"
840 done
841}
842
843source_has() {
844 local i
845 for i in $source; do
846 [ "$1" = "${i##*/}" ] && return 0
847 done
848 return 1
849}
850
851subpackages_has() {
852 local i
853 for i in $subpackages; do
854 [ "$1" = "${i%:*}" ] && return 0
855 done
856 return 1
857}
858
859list_has() {
860 local needle="$1"
861 local i
862 shift
863 for i in $@; do
864 [ "$needle" = "$i" ] && return 0
865 [ "$needle" = "!$i" ] && return 1
866 done
867 return 1
868}
869
870# same as list_has but we filter version info
871deplist_has() {
872 local needle="$1"
873 local i
874 shift
875 for i in $@; do
876 i=${i%[<>=]*}
877 [ "$needle" = "$i" ] && return 0
878 [ "$needle" = "!$i" ] && return 1
879 done
880 return 1
881}
882
883options_has() {
884 list_has "$1" $options
885}
886
887depends_has() {
888 deplist_has "$1" $depends
889}
890
891makedepends_has() {
892 deplist_has "$1" $makedepends
893}
894
895md5sums_has() {
896 list_has "$1" $md5sums
897}
898
899install_has() {
900 list_has "$1" $install
901}
902
903# install package after build
904post_add() {
905 local pkgf="$PKGDEST/$1-$pkgver-r$pkgrel.apk"
906 local deps i
907 if ! subpackages_has $1 && [ "$1" != "$pkgname" ]; then
908 die "$1 is not built by this APKBUILD"
909 fi
910 # recursively install dependencies that are provided by this APKBUILD
911 deps=$(apk index "$pkgf" 2>/dev/null | awk -F: '$1=="D" { print $2 }')
912 for i in $deps; do
913 if subpackages_has $i || [ "$i" = "$pkgname" ]; then
914 post_add $i || return 1
915 fi
916 done
917 $SUDO apk add -u "$pkgf" || die "Failed to install $1"
918}
919
920# create new aport from templates
921newaport() {
922 local pn=${newname%-[0-9]*}
923 local pv
924 if [ "$pn" != "$newname" ]; then
925 pv=${newname#$pn-}
926 fi
927 if [ -e "$pn"/APKBUILD ]; then
928 error "$pn/APKBUILD already exist"
929 return 1
930 fi
931 mkdir -p "$pn"
932 cd "$pn"
933 sed -e '1,/^\#*$/d' \
934 -e "s/^\(# Contributor: \).*/\1$PACKAGER/" \
935 -e "s/^\(# Maintainer: \).*/\1$PACKAGER/" \
936 -e "s/^pkgname=.*/pkgname=$pn/" \
937 -e "s/^pkgver=.*/pkgver=$pv/" \
938 "$datadir"/sample.APKBUILD > APKBUILD || return 1
939 #-e '1,/^\#$/d' \
940 if [ -n "$cpinitd" ]; then
941 cp "$datadir"/sample.initd $pn.initd
942 cp "$datadir"/sample.confd $pn.confd
943 cp "$datadir"/sample.pre-install $pn.pre-install
944 cp "$datadir"/sample.post-install $pn.post-install
945 sed -i -e "s/^install=.*/install=\"\$pkgname.pre-install \$pkgname.post-install\"/" \
946 -e "s/^source=\"\(.*\)\"/source=\"\1\n\t$pn.initd\n\t$pn.confd\n\t\$install\n\t\"/" \
947 APKBUILD
948
949 fi
950}
951
952installdeps() {
953 local deps i
954 sudo apk add --repository "$apkcache" --virtual .makedepends-$pkgname \
955 $makedepends
956}
957
958uninstalldeps (){
959 sudo apk del .makedepends-$pkgname
960}
961
962all() {
963 if up2date && [ -z "$force" ]; then
964 msg "Package is up to date"
965 else
966 apkcache
967 fi
968}
969
970usage() {
971 echo "$(basename $0) $abuild_ver"
972 echo "usage: ${0##*/} [options] [-i PKG] [-P REPODEST] [-p PKGDEST]"
973 echo " [-s SRCDEST] [cmd] ..."
974 echo " ${0##*/} [-c] -n PKGNAME[-PKGVER]"
975 echo "Options:"
976 echo " -d Disable dependency checking"
977 echo " -f Force specified cmd, even if they are already done"
978 echo " -h Show this help"
979 echo " -i Install PKG after successul build"
980 echo " -k Keep built packages, even if APKBUILD or sources are newer"
981 echo " -p Set package destination directory"
982 echo " -P Set PKGDEST to REPODEST/<repo>, where repo is the parents dir name"
983 echo " -q Quiet"
984 echo " -r Install missing dependencies from system repository (using sudo)"
985 echo " -R Recursively build and install missing dependencies (using sudo)"
986 echo " -s Set source package destination directory"
987 echo " -u Recursively build and upgrade all dependencies (using sudo)"
988 echo ""
989 echo " -n Create a new APKBUILD in a directory named PKGNAME"
990 echo " -c Copy a sample init.d, conf.d and install script to new directory"
991 echo ""
992 echo "Commands:"
993 echo " checksum Generate checksum to be included in APKBUILD"
994 echo " fetch Fetch sources to \$SRCDEST and verify checksums"
995 echo " sanitycheck Basic sanity check of APKBUILD"
996 echo " md5check Check md5sums"
997 echo " unpack Unpack sources to \$srcdir"
998 echo " build Compile and install package into \$pkgdir"
999 echo " listpkg List target packages"
1000 echo " package Create package in \$PKGDEST"
1001 echo " rootpkg Run '$0 build package' as fakeroot"
1002 echo " clean Remove temp build and install dirs"
1003 echo " cleanoldpkg Remove binary packages except current version"
1004 echo " cleanpkg Remove already built binary and source package"
1005 echo " cleancache Remove downloaded files from \$SRCDEST"
1006 echo " srcpkg Make a source package"
1007 echo " up2date Compare target and sources dates"
1008 echo " installdeps Install packages listed in makedepends and depends"
1009 echo " uninstalldeps Uninstall packages listed in makedepends and depends"
1010 echo ""
1011 exit 0
1012}
1013
1014APKBUILD="${APKBUILD:-./APKBUILD}"
1015unset force
1016unset recursive
1017while getopts "cdfhi:kin:p:P:qrRs:u" opt; do
1018 case $opt in
1019 'c') cpinitd=1;;
1020 'd') nodeps=1;;
1021 'f') force=1;;
1022 'h') usage;;
1023 'i') install_after="$install_after $OPTARG";;
1024 'k') keep=1;;
1025 'n') newname=$OPTARG;;
1026 'p') PKGDEST=$OPTARG;;
1027 'P') REPODEST=$OPTARG;;
1028 'q') quiet=1;;
1029 'r') install_deps=1;;
1030 'R') recursive=1;;
1031 's') SRCDEST=$OPTARG;;
1032 'u') upgrade=1
1033 recursive=1;;
1034 esac
1035done
1036shift $(( $OPTIND - 1 ))
1037
1038# If REPODEST is set then it will override the PKGDEST
1039if [ -n "$REPODEST" ]; then
1040 PKGDEST="$REPODEST/$repo"
1041fi
1042
1043# source the buildfile
1044if [ -z "$newname" ]; then
1045 [ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
1046 . "$APKBUILD"
1047fi
1048
1049# If we are handling a sub package then reset subpackages and install
1050if [ -n "$subpkgname" ]; then
1051 origsubpackages="$subpackages"
1052 subpackages=
1053 install=
1054fi
1055pkgdir="$pkgbasedir/$pkgname"
1056controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname}
1057
1058trap 'die "Aborted by user"' INT
1059set_xterm_title "abuild: $pkgname"
1060
1061if [ -z "$1" ] && [ -n "$newname" ]; then
1062 set "newaport"
1063fi
1064
1065if [ -z "$1" ]; then
1066 set all
1067fi
1068
1069while [ $# -gt 0 ]; do
1070 runpart $1
1071 shift
1072done
1073
1074for i in $install_after; do
1075 post_add $i
1076done
1077
1078cleanup
1079