abuild.in 19.5 KB
Newer Older
Natanael Copa's avatar
Natanael Copa committed
1 2 3 4 5 6 7 8 9 10
#!/bin/sh

# script to build apk packages (light version og makepkg)
# Copyright (c) 2008 Natanael Copa <natanael.copa@gmail.com>
#
# Distributed under GPL-2
#
# Depends on: busybox utilities, fakeroot, 
#

Natanael Copa's avatar
Natanael Copa committed
11 12
abuild_ver=@VERSION@
sysconfdir=@sysconfdir@
Natanael Copa's avatar
Natanael Copa committed
13 14 15

startdir="$PWD"
srcdir=${srcdir:-"$startdir/src"}
16
pkgdirbase=${pkgdirbase:-"$startdir/pkg"}
Natanael Copa's avatar
Natanael Copa committed
17
pkgrel=0
Natanael Copa's avatar
Natanael Copa committed
18 19
repo=${startdir%/*}
repo=${repo##*/}
Natanael Copa's avatar
Natanael Copa committed
20 21 22 23

# defaults
SRCDEST=${SRCDEST:-$startdir}
PKGDEST=${PKGDEST:-$startdir}
24
BUILD_BASE="binutils gcc make patch uclibc-dev"
Natanael Copa's avatar
Natanael Copa committed
25

26 27
SUDO=${SUDO:-"sudo"}

28
default_cmds="sanitycheck builddeps clean fetch unpack rootpkg"
Natanael Copa's avatar
Natanael Copa committed
29

Natanael Copa's avatar
Natanael Copa committed
30
# read config
Natanael Copa's avatar
Natanael Copa committed
31
ABUILD_CONF=${ABUILD_CONF:-"$sysconfdir/abuild.conf"}
Natanael Copa's avatar
Natanael Copa committed
32 33
[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"

34
# source functions
35 36
datadir=/usr/share/abuild

Natanael Copa's avatar
Natanael Copa committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#colors
if [ -n "$USE_COLORS" ]; then
	NORMAL="\033[1;0m"
	STRONG="\033[1;1m"
	RED="\033[1;31m"
	GREEN="\033[1;32m"
	YELLOW="\033[1;33m"
	BLUE="\033[1;34m"
fi	
	

# functions
msg() {
	local prompt="$GREEN>>>${NORMAL}"
	local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
	local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
	[ -z "$quiet" ] && printf "${prompt} ${name}${fake}: $@\n" >&2
}

warning() {
	local prompt="${YELLOW}>>> WARNING:${NORMAL}"
	local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
	local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
	printf "${prompt} ${name}${fake}: $@\n" >&2
}

error() {
	local prompt="${RED}>>> ERROR:${NORMAL}"
	local fake="${FAKEROOTKEY:+${BLUE}*${NORMAL}}"
	local name="${STRONG}${subpkgname:-$pkgname}${NORMAL}"
	printf "${prompt} ${name}${fake}: $@\n" >&2
}
69 70

	
Linux User's avatar
Linux User committed
71 72
set_xterm_title() {
	if [ "$TERM" = xterm ]; then
73
		 printf "\033]0;$1\007" >&2
Linux User's avatar
Linux User committed
74 75 76 77 78
	fi
} 

cleanup() {
	set_xterm_title ""
79
	if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then
80
		$SUDO apk del $uninstall_after
81
	fi
Linux User's avatar
Linux User committed
82 83
}

Natanael Copa's avatar
Natanael Copa committed
84
die() {
Linux User's avatar
Linux User committed
85
	error "$@"
Linux User's avatar
Linux User committed
86
	cleanup
Natanael Copa's avatar
Natanael Copa committed
87 88 89
	exit 1
}

90 91
# check if apkbuild is basicly sane
sanitycheck() {
Natanael Copa's avatar
Natanael Copa committed
92
	local i
93
	msg "Checking sanity of $APKBUILD..."
94 95 96
	[ -z "$pkgname" ] && die "Missing pkgname in APKBUILD"
	[ -z "${pkgname##* *}" ] && die "pkgname contains spaces"
	[ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
Natanael Copa's avatar
Natanael Copa committed
97
	[  "${pkgver##[0-9]}" == "$pkgver" ] && \
98 99 100 101 102 103
		die "pkgver does not start with a digit"
	[ -z "$pkgrel" ] && warning "Missing pkgrel in APKBUILD. Using pkgrel=0"
	[ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD"
	[ -z "$url" ] && die "Missing url in APKBUILD"
	[ -z "$license" ] && die "Missing license in APKBULID"

104 105 106
	if [ -n "$source" ]; then
		for i in $source; do
			md5sums_has ${i##*/} || die "${i##*/} is missing in md5sums"
107 108 109
			case "$i" in
				https://*) makedepends_has wget || die "wget must be in makedepends when source has https://" ;;
			esac
110 111
		done
	fi
Natanael Copa's avatar
Natanael Copa committed
112

113 114 115 116 117
	if [ -n "$md5sums" ]; then
		for i in $(echo "$md5sums" | awk '{ print $2 }'); do
			source_has $i || die "$i is missing in source"
		done
	fi
118

119 120 121
	# common spelling errors
	[ -n "$depend" ] && die "APKBUILD contains 'depend'. It should be depends"
	[ -n "$makedepend" ] && die "APKBUILD contains 'makedepend'. It should be makedepends"
Natanael Copa's avatar
Natanael Copa committed
122 123

	grep '^# Maintainer:' $APKBUILD >/dev/null || warning "No maintainer"
124 125 126 127
	return 0
}

md5check() {
Natanael Copa's avatar
Natanael Copa committed
128
	local dummy f
129 130 131
	if [ -z "$source" ]; then
		return 0
	fi
132
	if [ -z "$md5sums" ]; then
133
		die "Use 'abuild checksum' to generate/update the checksum(s)"
134
	fi
135 136 137
	if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
		die "Number of md5sums does not correspond to number of sources"
	fi
138
	fetch || return 1
139
	msg "Checking md5sums..."
140
	cd "$srcdir" && echo "$md5sums" | md5sum -c 
Natanael Copa's avatar
Natanael Copa committed
141 142 143 144 145
}

uri_fetch() {
	local uri="$1"
	local d="${s##*/}"	# $(basename $s)
146 147 148 149
	local opts
	[ -n "$quiet" ] && opts="-q"
	[ -f "$SRCDEST/$d" ] && return 0

150 151 152 153 154 155
	
	# we need GNU wget for this
	case "$uri" in
		https://*) opts="--no-check-certificate";;
	esac
	
Natanael Copa's avatar
Natanael Copa committed
156
	mkdir -p "$SRCDEST"
157 158 159
	if [ -f "$SRCDEST/$d.part" ]; then
		msg "Partial download found. Trying to resume"
		opts="$opts -c"
Natanael Copa's avatar
Natanael Copa committed
160
	fi
Linux User's avatar
Linux User committed
161
	msg "Fetching $uri"
162 163
	wget $opts -O "$SRCDEST/$d.part" "$uri" \
		&& mv "$SRCDEST/$d.part" "$SRCDEST/$d"
Natanael Copa's avatar
Natanael Copa committed
164 165
}

166 167
is_remote() {
	case "$1" in
168
		http://*|ftp://*|https://*)
169 170 171 172 173
			return 0;;
	esac
	return 1
}

Natanael Copa's avatar
Natanael Copa committed
174 175 176
fetch() {
	local s
	mkdir -p "$srcdir"
177 178 179 180 181 182 183
	for s in $source; do
		if is_remote "$s"; then
			uri_fetch "$s" || return 1
			ln -sf "$SRCDEST/${s##*/}" "$srcdir"/
		else		
			ln -sf "$startdir/$s" "$srcdir/"
		fi
Natanael Copa's avatar
Natanael Copa committed
184 185 186 187 188 189
	done
}

# unpack the sources
unpack() {
	local u
190
	md5check || return 1
Natanael Copa's avatar
Natanael Copa committed
191 192 193 194
	mkdir -p "$srcdir"
	for u in $source; do
		local s="$SRCDEST/${u##*/}"	# $(basename $s)
		case "$s" in
Natanael Copa's avatar
Natanael Copa committed
195
			*.tar.gz|*.tgz)
196
				msg "Unpacking $s..."
Natanael Copa's avatar
Natanael Copa committed
197 198
				tar -C "$srcdir" -zxf "$s" || return 1;;
			*.tar.bz2)
199
				msg "Unpacking $s..."
Natanael Copa's avatar
Natanael Copa committed
200
				tar -C "$srcdir" -jxf "$s" || return 1;;
201 202 203 204
			*.tar.lzma)
				msg "Unpacking $s..."
				unlzma -c "$s" | tar -C "$srcdir" -x  \
					|| return 1;;
Natanael Copa's avatar
Natanael Copa committed
205 206 207
			*.zip)
				msg "Unpacking $s..."
				unzip "$s" -d "$srcdir" || return 1;;
Natanael Copa's avatar
Natanael Copa committed
208 209 210 211 212 213
		esac
	done
}

# cleanup source and package dir
clean() {
214
	msg "Cleaning temporary build dirs..."
Natanael Copa's avatar
Natanael Copa committed
215
	rm -rf "$srcdir"
Natanael Copa's avatar
Natanael Copa committed
216
	rm -rf "$pkgdirbase"
Natanael Copa's avatar
Natanael Copa committed
217 218 219 220 221 222
}

# cleanup fetched sources
cleancache() {
	local s
	for s in $source; do
223 224 225 226
		if is_remote "$s"; then
			msg "Cleaning downloaded ${s##*/}..."
			rm -f "$SRCDEST/${s##*/}"
		fi
Natanael Copa's avatar
Natanael Copa committed
227 228 229 230 231
	done
}

cleanpkg() {
	local i
232
	msg "Cleaning built packages..."
233
	for i in $pkgname $subpackages; do
234
		local p="$i-$pkgver-r$pkgrel"
235
		rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz"
Natanael Copa's avatar
Natanael Copa committed
236 237 238
	done
}

239 240 241 242 243 244 245 246 247 248 249 250 251
# clean all packages except current
cleanoldpkg() {
	local i j
	msg "Cleaning all packages except $pkgver-r$pkgrel..."
	for i in $pkgname $subpackages; do
		for j in "$PKGDEST"/${i%:*}-[0-9]*.apk; do
			[ "$j" != "$PKGDEST/${i%:*}-$pkgver-r$pkgrel.apk" ] \
				&& rm -f "$j"
		done
	done
	return 0
}
	
Natanael Copa's avatar
Natanael Copa committed
252 253
runpart() {
	local part=$1
254
	[ -n "$DEBUG" ] && msg "$part"
Natanael Copa's avatar
Natanael Copa committed
255 256 257 258 259 260 261 262
	$part || die "$part failed"
}

# override those in your build script
build() {
	die "No build() function found in $APKBUILD"
}

263 264 265 266 267 268 269 270 271
get_split_func() {
	# get the 'func' from "sub-pkg:func"
	local func=${1##*:}

	# get 'func' from "sub-pkg-func" if there was no :func
	[ "$func" = "$1" ] && func=${func##*-}
	echo $func
}

272
prepare_subpackages() {
273
	if [ -z "$subpackages" ]; then
274 275
		return 0
	fi
Natanael Copa's avatar
Natanael Copa committed
276 277
	local i
	cd "$startdir"
278
	for i in $subpackages; do
279 280
		local func=$(get_split_func $i)
		# call abuild recursively, setting subpkg{dir,name}
281
		msg "Running split function $func..."
282
		subpkgdir="$pkgdirbase/${i%:*}" subpkgname="${i%:*}" \
283
			$0 $func prepare_package || return 1
Natanael Copa's avatar
Natanael Copa committed
284 285 286
	done
}

287
prepare_metafiles() {
288 289
	local name=${subpkgname:-$pkgname}
	[ -z "${name##* *}" ] && die "package name contains spaces"
290
	local dir=${subpkgdir:-$pkgdir}
291
	local pkg="$name-$pkgver-r$pkgrel.apk"
292
	local sub
Natanael Copa's avatar
Natanael Copa committed
293 294 295
	
	[ ! -d "$dir" ] && die "Missing $dir"
	cd "$dir"
296
	msg "Creating ${subpkgname:+sub}package $pkg..."
Natanael Copa's avatar
Natanael Copa committed
297 298 299
	local builddate=$(date -u "+%s")
	local size=$(du -sk | awk '{print $1 * 1024}')

300
	echo "# Generated by $(basename $0) $abuild_ver" >.PKGINFO
Natanael Copa's avatar
Natanael Copa committed
301 302 303 304 305
	if [ -n "$FAKEROOTKEY" ]; then
		echo "# using $(fakeroot -v)" >> .PKGINFO
	fi
	echo "# $(date -u)" >> .PKGINFO
	cat >> .PKGINFO <<EOF
306
pkgname = $name
307
pkgver = $pkgver-r$pkgrel
Natanael Copa's avatar
Natanael Copa committed
308 309 310 311 312 313
pkgdesc = $pkgdesc
url = $url
builddate = $builddate
packager = ${PACKAGER:-"Unknown"}
size = $size
EOF
314 315
	local i deps
	deps="$depends"
316 317 318 319 320 321 322 323
	if [ "$pkgname" != "busybox" ] && ! depends_has busbox; then
		for i in $install; do
			if head -n 1 "$srcdir/$i" | grep '^#!/bin/sh' >/dev/null ; then
				msg "Script found. busybox added as a dependency for $pkg"
				deps="$deps busybox"
				break
			fi
		done
324 325
	fi
	
Natanael Copa's avatar
Natanael Copa committed
326 327 328 329 330 331
	for i in $license; do
		echo "license = $i" >>.PKGINFO
	done
	for i in $replaces; do
		echo "replaces = $i" >>.PKGINFO
	done
332
	for i in $deps; do
Natanael Copa's avatar
Natanael Copa committed
333 334 335 336 337 338 339 340 341 342 343 344 345
		echo "depend = $i" >>.PKGINFO
	done
	for i in $conflicts; do
		echo "conflict = $i" >>.PKGINFO
	done
	for i in $provides; do
		echo "provides = $i" >>.PKGINFO
	done
	for i in $backup; do
		echo "backup = $i" >>.PKGINFO
	done

	local metafiles=".PKGINFO"
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
	for i in $install; do
		script=${i#$name}
		case "$script" in
			.install)
				warning "Deprecated .install script found."
				script=.INSTALL
				;;
			.pre-install|.post-install|.pre-upgrade|.post-upgrade|.pre-deinstall|.post-deinstall)
				msg "Adding $script"
				;;
			*) 	error "$script: Invalid install script"
				return 1
				;;
		esac
		cp "$srcdir/$i" "$dir/$script" || return 1
		chmod +x "$dir/$script"
		metafiles="$metafiles $script"
	done
364
	echo $metafiles | tr ' ' '\n' > "$dir"/.metafiles	
Natanael Copa's avatar
Natanael Copa committed
365 366
}

367
prepare_package() {
368
	options_has "!strip" ||	stripbin
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	prepare_metafiles
}

pkginfo_val() {
	local key="$1"
	local file="$2"
	awk -F ' = ' "\$1 == \"$key\" {print \$2}" "$file"
}

create_apks() {
	local file
	for file in "$pkgdirbase"/*/.PKGINFO; do
		local dir="${file%/.PKGINFO}"
		local name=$(pkginfo_val pkgname $file)
		local ver=$(pkginfo_val pkgver $file)
		local apk="$PKGDEST"/$name-$ver.apk
		(
		set *
		[ "$1" = '*' ] && set --
		cd "$dir" && tar -zcf "$apk" $(cat .metafiles) $@
		)
	done
Natanael Copa's avatar
Natanael Copa committed
391 392
}

393
# predefined splitfunc doc
394
default_doc() {
395
	depends="$depends_doc"
396
	install="$install_doc"
Natanael Copa's avatar
Natanael Copa committed
397
	local i
398
	for i in doc man info html sgml licenses gtk-doc; do
399 400 401
		if [ -d "$pkgdir/usr/share/$i" ]; then
			mkdir -p "$subpkgdir/usr/share"
			mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/"
Natanael Copa's avatar
Natanael Copa committed
402 403
		fi
	done
404 405 406
	
	rm -f "$subpkgdir/usr/share/info/dir"

407 408 409
#	# compress info and man pages
#	find "$subpkgdir/usr/share" \( -name '*.info' -o -name '*.info-[1-9]' \
#		-o -name '*.[1-9]' \) -exec gzip {} \;
410 411 412 413

	# remove if empty, ignore error (not empty)
	rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null

Natanael Copa's avatar
Natanael Copa committed
414
#	[ -d "$subpkgdir/usr/share/man" ] && depends="man"
Natanael Copa's avatar
Natanael Copa committed
415 416 417
	return 0
}

418 419 420 421
doc() {
	default_doc
}

422
# predefined splitfunc mod
423
default_mod() {
424
	depends="$kernel $depends_mod"
425
	install="$install_mod"
Natanael Copa's avatar
Natanael Copa committed
426
	for i in firmware modules; do
427 428 429
		if [ -d "$pkgdir/lib/$i" ]; then
			rm -rf "$subpkgdir/lib"
			mkdir -p "$subpkgdir/lib"
430
			mv "$pkgdir/lib/$i" "$subpkgdir/lib"
Natanael Copa's avatar
Natanael Copa committed
431 432 433 434
		fi
	done
}

435 436 437 438
mod() {
	default_mod
}

439
# predefined splitfunc dev
440
default_dev() {
441
	depends="$pkgname $depends_dev"
442
	install="$install_dev"
443
	cd "$pkgdir" || return 0
444 445 446 447 448
	for i in usr/include usr/lib/pkgconfig usr/share/aclocal\
			usr/share/gettext usr/bin/*-config	\
			$(find -name include -type d) 		\
			$(find usr/ -name '*.[acho]' -o -name '*.la' \
			2>/dev/null); do
449 450
		if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
			d="$subpkgdir/${i%/*}"	# dirname $i
Natanael Copa's avatar
Natanael Copa committed
451
			mkdir -p "$d"
452
			mv "$pkgdir/$i" "$d"
453
			rmdir "$pkgdir/${i%/*}" 2>/dev/null
Natanael Copa's avatar
Natanael Copa committed
454 455
		fi
	done
Natanael Copa's avatar
Natanael Copa committed
456
	return 0
Natanael Copa's avatar
Natanael Copa committed
457 458
}

459 460 461 462
dev() {
	default_dev
}

Natanael Copa's avatar
Natanael Copa committed
463 464
# build and package in fakeroot
rootpkg() {
Natanael Copa's avatar
Natanael Copa committed
465
	cd "$startdir"
466
	msg "Entering fakeroot..."
467
	fakeroot $0 build prepare_subpackages prepare_package create_apks
Natanael Copa's avatar
Natanael Copa committed
468 469 470
}

srcpkg() {
471
	local p="$pkgname-$pkgver-$pkgrel"
Natanael Copa's avatar
Natanael Copa committed
472
	local prefix="${startdir##*/}"
Natanael Copa's avatar
Natanael Copa committed
473 474 475 476 477
	local i files="$prefix/APKBUILD"
	for i in $source; do
		files="$files $prefix/${i##*/}"
	done
	mkdir -p "$PKGDEST"
478
	msg "Creating source package $p.src.tar.gz..."
479
	(cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files) 
Natanael Copa's avatar
Natanael Copa committed
480 481
}

482 483
# check if package is up to date
up2date() {
484
	local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk"
485
	local i s
Natanael Copa's avatar
Natanael Copa committed
486
	cd "$startdir"
487 488 489 490 491
	for i in $pkgname $subpackages; do
		[ -f "$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" ] || return 1
	done
	[ -n "$keep" ] && return 0

492
	for i in $source APKBUILD; do
493 494 495 496 497 498
		local s
		if is_remote "$i"; then
			s="$SRCDEST/${i##*/}"	# $(basename $i)
		else
			s="$startdir/${i##*/}"
		fi
499 500 501 502 503 504 505
		if [ "$s" -nt "$pkg" ]; then
			return 1
		fi
	done
	return 0
}

506 507 508 509 510 511 512 513 514 515 516 517 518
# source all APKBUILDs and output:
#  1) origin of package
#  2) all dependencies
# the output is i in a format easy parseable for awk
depparse_aports() {
	# lets run this in a subshell since we source all APKBUILD here
	(
	aportsdir=$(realpath ${APKBUILD%/APKBUILD}/../..)
	for i in $aportsdir/*/*/APKBUILD; do
		pkgname=
		subpackages=
		depends=
		makedepends=
519
		. $i
520
		dir=${i%/APKBUILD}
521 522 523 524 525 526 527 528
		deps=
		# filter out conflicts from deps
		for j in $depends $makedepends; do
			case "$j" in
				!*) continue;;
			esac
			deps="$deps $j"
		done
529
		for j in $pkgname $subpackages; do
530
			echo "o ${j%%:*} $dir"
531
			set -- $deps
532 533 534 535 536 537 538
			echo -n "d ${j%%:*} $1"
			shift
			while [ $# -gt 0 ]; do
				echo -n ",$1"
				shift
			done
			echo
539 540
		done
	done
541
	)
542 543
}

544
deptrace() {
545 546
	local deps="$@"
	[ -z "$deps" ] && deps="$BUILD_BASE $depends $makedepends"
547 548 549
	( 	depparse_aports 
		if [ -z "$upgrade" ]; then
			# list installed pkgs and prefix with 'i '
Natanael Copa's avatar
Natanael Copa committed
550
			apk info -q | sort |  sed 's/^/i /'
551
		fi
552
	) | awk -v pkgs="$deps" '
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

	function depgraph(pkg,	a, i) {
		if (visited[pkg])
			return 0;
		visited[pkg] = 1;
		split(deps[pkg], a, ",");
		for (i in a)
			depgraph(a[i]);
		print pkg ":" origin[pkg];

	}

	$1 == "i" { visited[$2] = 1 }
	$1 == "o" { origin[$2] = $3 }
	$1 == "d" { deps[$2] = $3 }
	END {
		split(pkgs, pkgarray);
		for (i in pkgarray)
			depgraph(pkgarray[i]);
	}
	'
}

# build and install dependencies
builddeps() {
578 579
	local deps alldeps pkg i dir ver missing installed_deps
	msg "Analyzing dependencies..."
580 581
	deps="$BUILD_BASE $makedepends"

582

583 584 585 586 587
	# add depends unless it is a subpackage
	for i in $depends; do
		subpackages_has $i || deps="$deps $i"
	done

588
	installed_deps=$(apk info -e $deps)
589
	# find which deps are missing
590
	for i in $deps; do
591
		if [ "${i#\!}" != "$i" ]; then
592
			list_has ${i#\!} $installed_deps \
593
				&& die "Conflicting package ${i#\!} is installed."
594
		elif ! list_has $i $installed_deps; then
595 596 597 598 599 600 601 602 603 604 605
			if [ -z "$install_deps" ] && [ -z "$recursive" ]; then
				die "Missing dependency $i. Use -r to autoinstall or -R to build"
			fi
			missing="$missing $i"
		fi
	done

	[ -z "$missing" ] && return 0

	if [ -n "$install_deps" ] &&  $SUDO apk add $missing; then
		uninstall_after="$missing $uninstall_after"
606 607
		return 0
	fi
608 609 610 611
	
	[ -z "$recursive" ] && return 1
	
	for i in $(deptrace $missing); do
612 613 614 615 616
		# i = pkg:dir
		local dir=${i#*:}
		local pkg=${i%:*}
		msg "Entering $dir"
		cd "$dir" || return 1
617
		$0 -k -i $pkg || return 1
618
		uninstall_after="$pkg $uninstall_after"
619 620 621
	done
}

622
# replace the md5sums in the APKBUILD
Natanael Copa's avatar
Natanael Copa committed
623 624
checksum() {
	local s files
625
	[ -z "$source" ] && return 0
Natanael Copa's avatar
Natanael Copa committed
626
	fetch
627
	msg "Updating the md5sums in APKBUILD..."
Natanael Copa's avatar
Natanael Copa committed
628 629 630 631
	for s in $source; do
		files="$files ${s##*/}"
	done
	md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
632 633
	sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
	echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
Natanael Copa's avatar
Natanael Copa committed
634 635
}

636
stripbin() {
637
	local bin
638 639
	cd "${subpkgdir:-$pkgdir}" || return 1
	msg "Stripping binaries"
640
	find . -type f 2>/dev/null | while read bin; do
641 642 643 644 645 646 647 648 649 650 651
		local opt=
		case "$(file -biz "$bin")" in
			*/x-sharedlib*|*/x-archive*)
				strip --strip-debug "$bin";;
			*/x-executable*)
				strip "$bin";;
		esac
	done
	return 0
}

652 653 654 655 656 657 658 659
# simply list target apks
listpkg() {
	local i 
	for i in $pkgname $subpackages; do
		echo "${i%:*}-$pkgver-r$pkgrel.apk"
	done
}

Natanael Copa's avatar
Natanael Copa committed
660 661 662 663 664 665 666 667
source_has() {
	local i
	for i in $source; do
		[ "$1" = "${i##*/}" ] && return 0
	done
	return 1
}

Natanael Copa's avatar
Natanael Copa committed
668 669 670 671 672 673 674 675
subpackages_has() {
	local i
	for i in $subpackages; do
		[ "$1" = "${i%:*}" ] && return 0
	done
	return 1
}

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
list_has() {
	local needle="$1"
	local i
	shift
	for i in $@; do
		[ "$needle" = "$i" ] && return 0
		[ "$needle" = "!$i" ] && return 1
	done
	return 1
}

options_has() {
	list_has "$1" $options
}

691 692 693 694
depends_has() {
	list_has "$1" $depends
}

695 696 697 698
makedepends_has() {
	list_has "$1" $makedepends
}

Natanael Copa's avatar
Natanael Copa committed
699 700 701 702
md5sums_has() {
	list_has "$1" $md5sums
}

Natanael Copa's avatar
Natanael Copa committed
703 704 705 706 707 708 709 710 711 712 713 714 715 716
# install package after build
post_add() {
	local pkgf="$PKGDEST/$1-$pkgver-r$pkgrel.apk"
	local deps i
	if ! subpackages_has $1 && [ "$1" != "$pkgname" ]; then
		die "$1 is not built by this APKBUILD"
	fi
	# recursively install dependencies that are provided by this APKBUILD
	deps=$(apk index "$pkgf" 2>/dev/null | awk -F: '$1=="D" { print $2 }')
	for i in $deps; do
		if subpackages_has $i || [ "$i" = "$pkgname" ]; then
			post_add $i || return 1
		fi
	done
717
	$SUDO apk add -u "$pkgf" || die "Failed to install $1"
Natanael Copa's avatar
Natanael Copa committed
718 719
}

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
# create new aport from templates
newaport() {
	local pn=${newname%-[0-9]*}
	local pv
	if [ "$pn" != "$newname" ]; then
		pv=${newname#$pn-}
	fi
	if [ -e "$pn"/APKBUILD ]; then
		error "$pn/APKBUILD already exist"
		return 1
	fi
	mkdir -p "$pn"
	cd "$pn"
	sed 	-e '1,/^\#*$/d' \
		-e "s/^\(# Contributor: \).*/\1$PACKAGER/" \
		-e "s/^\(# Maintainer: \).*/\1$PACKAGER/" \
		-e "s/^pkgname=.*/pkgname=$pn/" \
		-e "s/^pkgver=.*/pkgver=$pv/" \
		"$datadir"/sample.APKBUILD > APKBUILD || return 1
	#-e '1,/^\#$/d' \
	if [ -n "$cpinitd" ]; then
		cp "$datadir"/sample.initd $pn.initd
		cp "$datadir"/sample.confd $pn.confd
743 744 745
		cp "$datadir"/sample.pre-install $pn.pre-install
		cp "$datadir"/sample.post-install $pn.post-install
		sed -i -e "s/^install=.*/install=\"\$pkgname.pre-install \$pkgname.post-install\"/" \
746 747 748 749 750
			-e "s/^source=\"\(.*\)\"/source=\"\1\n\t$pn.initd\n\t$pn.confd\n\t\$install\n\t\"/" \
			APKBUILD
		
	fi
}
751 752 753 754 755 756 757 758

installdeps() {
	sudo apk add $depends $makedepends
}

uninstalldeps (){
	sudo apk del $depends $makedepends
}
759
	
Natanael Copa's avatar
Natanael Copa committed
760
usage() {
761
	echo "$(basename $0) $abuild_ver"
762 763
	echo "usage: ${0##*/} [options] [-i PKG] [-P REPODEST] [-p PKGDEST]"
	echo "              [-s SRCDEST] [cmd] ..."
764
	echo "       ${0##*/} [-c] -n PKGNAME[-PKGVER]"
Natanael Copa's avatar
Natanael Copa committed
765 766
	echo "Options:"
	echo " -f  Force specified cmd, even if they are already done"
767 768
	echo " -h  Show this help"
	echo " -i  Install PKG after successul build"
769
	echo " -k  Keep built packages, even if APKBUILD or sources are newer"
770
	echo " -p  Set package destination directory"
771
	echo " -P  Set PKGDEST to REPODEST/<repo>, where repo is the parents dir name" 
Natanael Copa's avatar
Natanael Copa committed
772
	echo " -q  Quiet"
773 774
	echo " -r  Install missing dependencies from system repository (using sudo)"
	echo " -R  Recursively build and install missing dependencies (using sudo)"
775
	echo " -s  Set source package destination directory"
776
	echo " -u  Recursively build and upgrade all dependencies (using sudo)"
Natanael Copa's avatar
Natanael Copa committed
777
	echo ""
778 779 780
	echo " -n  Create a new APKBUILD in a directory named PKGNAME"
	echo " -c  Copy a sample init.d, conf.d and install script to new directory"
	echo ""
Natanael Copa's avatar
Natanael Copa committed
781
	echo "Commands:"
782
	echo "  checksum    Generate checksum to be included in APKBUILD"
783 784 785 786 787
	echo "  fetch       Fetch sources to \$SRCDEST and verify checksums"
	echo "  sanitycheck Basic sanity check of APKBUILD"
	echo "  md5check    Check md5sums"
	echo "  unpack      Unpack sources to \$srcdir"
	echo "  build       Compile and install package into \$pkgdir"
788
	echo "  listpkg     List target packages"
789 790 791
	echo "  package     Create package in \$PKGDEST"
	echo "  rootpkg     Run '$0 build package' as fakeroot"
	echo "  clean       Remove temp build and install dirs"
792
	echo "  cleanoldpkg Remove binary packages except current version"
793 794 795 796
	echo "  cleanpkg    Remove already built binary and source package"
	echo "  cleancache  Remove downloaded files from \$SRCDEST"
	echo "  srcpkg      Make a source package"
	echo "  up2date     Compare target and sources dates"
797 798
	echo "  installdeps Install packages listed in makedepends and depends"
	echo "  uninstalldeps Uninstall packages listed in makedepends and depends"
Natanael Copa's avatar
Natanael Copa committed
799 800 801 802 803
	echo ""
	exit 0
}

APKBUILD="${APKBUILD:-./APKBUILD}"
804 805
unset force
unset recursive
806
while getopts "cfhi:kin:p:P:qrRs:u" opt; do
Natanael Copa's avatar
Natanael Copa committed
807
	case $opt in
808
		'c') cpinitd=1;;
Natanael Copa's avatar
Natanael Copa committed
809
		'f') force=1;;
810 811
		'h') usage;;
		'i') install_after="$install_after $OPTARG";;
812
		'k') keep=1;;
813
		'n') newname=$OPTARG;;
814
		'p') PKGDEST=$OPTARG;;
815
		'P') REPODEST=$OPTARG;;
Natanael Copa's avatar
Natanael Copa committed
816
		'q') quiet=1;;
817 818
		'r') install_deps=1;;
		'R') recursive=1;;
819
		's') SRCDEST=$OPTARG;;
820 821
		'u') upgrade=1
		     recursive=1;;
Natanael Copa's avatar
Natanael Copa committed
822 823 824 825
	esac
done
shift $(( $OPTIND - 1 ))

826 827 828 829 830
# If REPODEST is set then it will override the PKGDEST
if [ -n "$REPODEST" ]; then
	PKGDEST="$REPODEST/$repo"
fi

831
# source the buildfile
832 833 834 835
if [ -z "$newname" ]; then
	[ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
	. "$APKBUILD"
fi
836

837
# If we are handling a sub package then reset subpackages and install
838 839
if [ -n "$subpkgname" ]; then
	subpackages=
840
	install=
841
fi
842
pkgdir="${pkgdirbase}/$pkgname"
Natanael Copa's avatar
Natanael Copa committed
843 844

trap 'die "Aborted by user"' INT
Linux User's avatar
Linux User committed
845
set_xterm_title "abuild: $pkgname"
Natanael Copa's avatar
Natanael Copa committed
846

847 848 849
if [ -z "$1" ] && [ -n "$newname" ]; then
	set "newaport"
fi
Natanael Copa's avatar
Natanael Copa committed
850 851

if [ -z "$1" ]; then
Natanael Copa's avatar
Natanael Copa committed
852
	if up2date && [ -z "$force" ]; then
Natanael Copa's avatar
Natanael Copa committed
853
		msg "Package is up to date"
854 855 856
	else
		set $default_cmds
	fi
Natanael Copa's avatar
Natanael Copa committed
857 858 859 860 861 862
fi

while [ $# -gt 0 ]; do
	runpart $1
	shift
done
863 864

for i in $install_after; do
Natanael Copa's avatar
Natanael Copa committed
865
	post_add $i
866 867
done

Linux User's avatar
Linux User committed
868
cleanup
Natanael Copa's avatar
Natanael Copa committed
869