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 365 366
	echo $metafiles | tr ' ' '\n' > "$dir"/.metafiles

	find -name '*.so' | sed 's:.*/::' >"$dir"/.provides-so
Natanael Copa's avatar
Natanael Copa committed
367 368
}

369
prepare_package() {
370
	options_has "!strip" ||	stripbin
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
	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
393 394
}

395
# predefined splitfunc doc
396
default_doc() {
397
	depends="$depends_doc"
398
	install="$install_doc"
Natanael Copa's avatar
Natanael Copa committed
399
	local i
400
	for i in doc man info html sgml licenses gtk-doc; do
401 402 403
		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
404 405
		fi
	done
406 407 408
	
	rm -f "$subpkgdir/usr/share/info/dir"

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

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

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

420 421 422 423
doc() {
	default_doc
}

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

437 438 439 440
mod() {
	default_mod
}

441
# predefined splitfunc dev
442
default_dev() {
443
	depends="$pkgname $depends_dev"
444
	install="$install_dev"
445
	cd "$pkgdir" || return 0
446 447 448 449 450
	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
451 452
		if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
			d="$subpkgdir/${i%/*}"	# dirname $i
Natanael Copa's avatar
Natanael Copa committed
453
			mkdir -p "$d"
454
			mv "$pkgdir/$i" "$d"
455
			rmdir "$pkgdir/${i%/*}" 2>/dev/null
Natanael Copa's avatar
Natanael Copa committed
456 457
		fi
	done
Natanael Copa's avatar
Natanael Copa committed
458
	return 0
Natanael Copa's avatar
Natanael Copa committed
459 460
}

461 462 463 464
dev() {
	default_dev
}

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

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

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

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

508 509 510 511 512 513 514 515 516 517 518 519 520
# 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=
521
		. $i
522
		dir=${i%/APKBUILD}
523 524 525 526 527 528 529 530
		deps=
		# filter out conflicts from deps
		for j in $depends $makedepends; do
			case "$j" in
				!*) continue;;
			esac
			deps="$deps $j"
		done
531
		for j in $pkgname $subpackages; do
532
			echo "o ${j%%:*} $dir"
533
			set -- $deps
534 535 536 537 538 539 540
			echo -n "d ${j%%:*} $1"
			shift
			while [ $# -gt 0 ]; do
				echo -n ",$1"
				shift
			done
			echo
541 542
		done
	done
543
	)
544 545
}

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

	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() {
580 581
	local deps alldeps pkg i dir ver missing installed_deps
	msg "Analyzing dependencies..."
582 583
	deps="$BUILD_BASE $makedepends"

584

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

590
	installed_deps=$(apk info -e $deps)
591
	# find which deps are missing
592
	for i in $deps; do
593
		if [ "${i#\!}" != "$i" ]; then
594
			list_has ${i#\!} $installed_deps \
595
				&& die "Conflicting package ${i#\!} is installed."
596
		elif ! list_has $i $installed_deps; then
597 598 599 600 601 602 603 604 605 606 607
			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"
608 609
		return 0
	fi
610 611 612 613
	
	[ -z "$recursive" ] && return 1
	
	for i in $(deptrace $missing); do
614 615 616 617 618
		# i = pkg:dir
		local dir=${i#*:}
		local pkg=${i%:*}
		msg "Entering $dir"
		cd "$dir" || return 1
619
		$0 -k -i $pkg || return 1
620
		uninstall_after="$pkg $uninstall_after"
621 622 623
	done
}

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

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

654 655 656 657 658 659 660 661
# 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
662 663 664 665 666 667 668 669
source_has() {
	local i
	for i in $source; do
		[ "$1" = "${i##*/}" ] && return 0
	done
	return 1
}

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

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
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
}

693 694 695 696
depends_has() {
	list_has "$1" $depends
}

697 698 699 700
makedepends_has() {
	list_has "$1" $makedepends
}

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

Natanael Copa's avatar
Natanael Copa committed
705 706 707 708 709 710 711 712 713 714 715 716 717 718
# 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
719
	$SUDO apk add -u "$pkgf" || die "Failed to install $1"
Natanael Copa's avatar
Natanael Copa committed
720 721
}

722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
# 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
745 746 747
		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\"/" \
748 749 750 751 752
			-e "s/^source=\"\(.*\)\"/source=\"\1\n\t$pn.initd\n\t$pn.confd\n\t\$install\n\t\"/" \
			APKBUILD
		
	fi
}
753 754 755 756 757 758 759 760

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

uninstalldeps (){
	sudo apk del $depends $makedepends
}
761
	
Natanael Copa's avatar
Natanael Copa committed
762
usage() {
763
	echo "$(basename $0) $abuild_ver"
764 765
	echo "usage: ${0##*/} [options] [-i PKG] [-P REPODEST] [-p PKGDEST]"
	echo "              [-s SRCDEST] [cmd] ..."
766
	echo "       ${0##*/} [-c] -n PKGNAME[-PKGVER]"
Natanael Copa's avatar
Natanael Copa committed
767 768
	echo "Options:"
	echo " -f  Force specified cmd, even if they are already done"
769 770
	echo " -h  Show this help"
	echo " -i  Install PKG after successul build"
771
	echo " -k  Keep built packages, even if APKBUILD or sources are newer"
772
	echo " -p  Set package destination directory"
773
	echo " -P  Set PKGDEST to REPODEST/<repo>, where repo is the parents dir name" 
Natanael Copa's avatar
Natanael Copa committed
774
	echo " -q  Quiet"
775 776
	echo " -r  Install missing dependencies from system repository (using sudo)"
	echo " -R  Recursively build and install missing dependencies (using sudo)"
777
	echo " -s  Set source package destination directory"
778
	echo " -u  Recursively build and upgrade all dependencies (using sudo)"
Natanael Copa's avatar
Natanael Copa committed
779
	echo ""
780 781 782
	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
783
	echo "Commands:"
784
	echo "  checksum    Generate checksum to be included in APKBUILD"
785 786 787 788 789
	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"
790
	echo "  listpkg     List target packages"
791 792 793
	echo "  package     Create package in \$PKGDEST"
	echo "  rootpkg     Run '$0 build package' as fakeroot"
	echo "  clean       Remove temp build and install dirs"
794
	echo "  cleanoldpkg Remove binary packages except current version"
795 796 797 798
	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"
799 800
	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
801 802 803 804 805
	echo ""
	exit 0
}

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

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

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

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

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

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

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

while [ $# -gt 0 ]; do
	runpart $1
	shift
done
865 866

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

Linux User's avatar
Linux User committed
870
cleanup
Natanael Copa's avatar
Natanael Copa committed
871