abuild 9.53 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, 
#

Linux User's avatar
Linux User committed
11
myver=0.6
Natanael Copa's avatar
Natanael Copa committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25

# read config
MAKEAPK_CONF=${MAKEAPK_CONF:-/etc/abuild.conf}
[ -f "$MAKEAPK_CONF" ] && . "$MAKEAPK_CONF"

startdir="$PWD"
srcdir=${srcdir:-"$startdir/src"}
pkgdir=${pkgdir:-"$startdir/pkg"}
pkgrel=0

# defaults
SRCDEST=${SRCDEST:-$startdir}
PKGDEST=${PKGDEST:-$startdir}

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

# functions
Natanael Copa's avatar
Natanael Copa committed
29
msg() {
Natanael Copa's avatar
Natanael Copa committed
30
	local sub=
31 32
	[ -n "$subpkgname" ] && sub="(sub)"
	[ -z "$quiet" ] && echo ">>> ${subpkgname:-$pkgname} $sub:" "$@" >&2
Natanael Copa's avatar
Natanael Copa committed
33 34 35 36 37 38 39 40
}

warning() {
	echo ">>> Warning:" "$@" >&2
}

die() {
	quiet=
Natanael Copa's avatar
Natanael Copa committed
41
	msg "$@" >&2
Natanael Copa's avatar
Natanael Copa committed
42 43 44
	exit 1
}

45 46 47 48 49
# check if apkbuild is basicly sane
sanitycheck() {
	[ -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
50
	[  "${pkgver##[0-9]}" == "$pkgver" ] && \
51 52 53 54 55 56
		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"

57 58 59 60
	if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
		die "Number of md5sums does not correspond to number of sources"
	fi

61 62 63 64 65 66 67 68
	# common spelling errors
	[ -n "$depend" ] && die "APKBUILD contains 'depend'. It should be depends"
	[ -n "$makedepend" ] && die "APKBUILD contains 'makedepend'. It should be makedepends"

	return 0
}

md5check() {
69 70 71
	if [ -z "$source" ]; then
		return 0
	fi
72 73 74
	if [ -z "$md5sums" ]; then
		die "Use 'abuild checksum >>$APKBUILD' to generate a checksum"
	fi
75 76 77 78

	if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
		die "Number of md5sums does not correspond to number of sources"
	fi
79
	cd "$srcdir" && echo "$md5sums" | md5sum -c 
Natanael Copa's avatar
Natanael Copa committed
80 81 82 83 84
}

uri_fetch() {
	local uri="$1"
	local d="${s##*/}"	# $(basename $s)
85 86 87 88
	local opts
	[ -n "$quiet" ] && opts="-q"
	[ -f "$SRCDEST/$d" ] && return 0

Natanael Copa's avatar
Natanael Copa committed
89
	mkdir -p "$SRCDEST"
90 91 92
	if [ -f "$SRCDEST/$d.part" ]; then
		msg "Partial download found. Trying to resume"
		opts="$opts -c"
Natanael Copa's avatar
Natanael Copa committed
93
	fi
94 95
	wget $opts -O "$SRCDEST/$d.part" "$uri" \
		&& mv "$SRCDEST/$d.part" "$SRCDEST/$d"
Natanael Copa's avatar
Natanael Copa committed
96 97 98 99 100 101 102 103 104
}

fetch() {
	local s
	mkdir -p "$srcdir"
	for s in $source; do 
		case "$s" in
			http://*|ftp://*)
				uri_fetch "$s" || return 1
105 106 107 108
				ln -sf "$SRCDEST/${s##*/}" "$srcdir"/
				;;
			*)
				ln -s "$startdir/$s" "$srcdir/"
Natanael Copa's avatar
Natanael Copa committed
109 110 111 112 113 114 115 116 117 118 119 120
				;;
		esac
	done
}

# unpack the sources
unpack() {
	local u
	mkdir -p "$srcdir"
	for u in $source; do
		local s="$SRCDEST/${u##*/}"	# $(basename $s)
		case "$s" in
Natanael Copa's avatar
Natanael Copa committed
121
			*.tar.gz|*.tgz)
Natanael Copa's avatar
Natanael Copa committed
122 123 124 125 126 127 128 129 130 131 132 133
				tar -C "$srcdir" -zxf "$s" || return 1;;
			*.tar.bz2)
				tar -C "$srcdir" -jxf "$s" || return 1;;
		esac
	done
}

# cleanup source and package dir
clean() {
	rm -rf "$srcdir"
	rm -rf "$pkgdir"
	local i
Natanael Copa's avatar
Natanael Copa committed
134 135
	for i in $subpackages; do
		rm -rf "$pkgdir-$(get_split_func $i)"
Natanael Copa's avatar
Natanael Copa committed
136 137 138 139 140 141 142 143 144
	done
}

# cleanup fetched sources
cleancache() {
	local s
	for s in $source; do
		case "$s" in
			http:/*|ftp:/*)
Natanael Copa's avatar
Natanael Copa committed
145
				rm -f "$SRCDEST/$(basename $s)";;
Natanael Copa's avatar
Natanael Copa committed
146 147 148 149 150 151
		esac
	done
}

cleanpkg() {
	local i
152 153 154
	for i in $pkgname $subpackages; do
		local p="$i-$pkgver-$pkgrel"
		rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz"
Natanael Copa's avatar
Natanael Copa committed
155 156 157 158 159
	done
}

runpart() {
	local part=$1
Natanael Copa's avatar
Natanael Copa committed
160
	msg "$part"
Natanael Copa's avatar
Natanael Copa committed
161 162 163 164 165 166 167 168
	$part || die "$part failed"
}

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

Natanael Copa's avatar
Natanael Copa committed
169 170 171 172 173 174 175 176 177
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
}

Natanael Copa's avatar
Natanael Copa committed
178
subpkg() {
Natanael Copa's avatar
Natanael Copa committed
179
	if [ -z "$subpackages" ]; then
180 181
		return 0
	fi
Natanael Copa's avatar
Natanael Copa committed
182 183
	local i
	cd "$startdir"
184
	for i in $subpackages; do
Natanael Copa's avatar
Natanael Copa committed
185 186 187 188
		local func=$(get_split_func $i)
		# call abuild recursively, setting subpkg{dir,name}
		subpkgdir="$startdir/pkg-$func" subpkgname="$i" \
			$0 $func package || return 1
Natanael Copa's avatar
Natanael Copa committed
189 190 191 192
	done
}

package_apk() {
193 194
	local name=${subpkgname:-$pkgname}
	[ -z "${name##* *}" ] && die "package name contains spaces"
195
	local dir=${subpkgdir:-$pkgdir}
196
	local pkg="$name-$pkgver-r$pkgrel.apk"
Natanael Copa's avatar
Natanael Copa committed
197 198 199 200 201 202 203 204 205 206 207 208 209
	
	[ ! -d "$dir" ] && die "Missing $dir"
	cd "$dir"
	msg "Creating $pkg"
	local builddate=$(date -u "+%s")
	local size=$(du -sk | awk '{print $1 * 1024}')

	echo "# Generated by $(basename $0) $myver" >.PKGINFO
	if [ -n "$FAKEROOTKEY" ]; then
		echo "# using $(fakeroot -v)" >> .PKGINFO
	fi
	echo "# $(date -u)" >> .PKGINFO
	cat >> .PKGINFO <<EOF
210
pkgname = $name
211
pkgver = $pkgver-r$pkgrel
Natanael Copa's avatar
Natanael Copa committed
212 213 214 215 216 217
pkgdesc = $pkgdesc
url = $url
builddate = $builddate
packager = ${PACKAGER:-"Unknown"}
size = $size
EOF
Natanael Copa's avatar
Natanael Copa committed
218
	local i
Natanael Copa's avatar
Natanael Copa committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

	for i in $license; do
		echo "license = $i" >>.PKGINFO
	done
	for i in $replaces; do
		echo "replaces = $i" >>.PKGINFO
	done
	for i in $depends; do
		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"
Natanael Copa's avatar
Natanael Copa committed
240 241 242
	if [ -n "$install" ]; then
		cp "$srcdir/$install" "$dir/.INSTALL" || return 1
		chmod +x "$dir/.INSTALL"
Natanael Copa's avatar
Natanael Copa committed
243
		metafiles="$metafiles .INSTALL"
Natanael Copa's avatar
Natanael Copa committed
244
	fi
Natanael Copa's avatar
Natanael Copa committed
245 246 247 248 249 250 251 252

#	for i in pre-install post-install pre-deinstall post-deinstall; do
#		[ -f ../$i ] && cp ../$i "$db"/
#	done
	
	set *
	[ "$1" = '*' ] && set --
	( cd "$dir" && tar -zcf "$PKGDEST/$pkg" $metafiles $@ )
Natanael Copa's avatar
Natanael Copa committed
253 254 255 256 257 258
}

package() {
	package_apk
}

259
# predefined splitfunc doc
Natanael Copa's avatar
Natanael Copa committed
260 261 262 263
doc() {
	depends=""
	local i
	for i in doc man info html sgml; do
264 265 266
		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
267 268
		fi
	done
269 270 271 272

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

273
	[ -d "$subpkgdir/usr/share/man" ] && depends="man"
Natanael Copa's avatar
Natanael Copa committed
274 275 276
	return 0
}

277
# predefined splitfunc mod
Natanael Copa's avatar
Natanael Copa committed
278 279 280
mod() {
	depends="$kernel"
	for i in firmware modules; do
281 282 283
		if [ -d "$pkgdir/lib/$i" ]; then
			rm -rf "$subpkgdir/lib"
			mkdir -p "$subpkgdir/lib"
284
			mv "$pkgdir/lib/$i" "$subpkgdir/lib"
Natanael Copa's avatar
Natanael Copa committed
285 286 287 288
		fi
	done
}

289
# predefined splitfunc dev
Natanael Copa's avatar
Natanael Copa committed
290
dev() {
291 292
	depends="$pkgname"
	for i in $(cd "$pkgdir" && find usr/lib -name '*.a' -o \
Natanael Copa's avatar
Natanael Copa committed
293 294
			-name '*.la' -o -name '*.o' 2>/dev/null) \
			usr/include usr/lib/pkgconfig usr/share/aclocal; do
295 296
		if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
			d="$subpkgdir/${i%/*}"	# dirname $i
Natanael Copa's avatar
Natanael Copa committed
297
			mkdir -p "$d"
298
			mv "$pkgdir/$i" "$d"
Natanael Copa's avatar
Natanael Copa committed
299 300 301 302 303 304
		fi
	done
}

# build and package in fakeroot
rootpkg() {
Natanael Copa's avatar
Natanael Copa committed
305
	cd "$startdir"
Natanael Copa's avatar
Natanael Copa committed
306 307 308 309
	fakeroot $0 build subpkg package
}

srcpkg() {
310
	local p="$pkgname-$pkgver-$pkgrel"
Natanael Copa's avatar
Natanael Copa committed
311
	local prefix="${startdir##*/}"
Natanael Copa's avatar
Natanael Copa committed
312 313 314 315 316
	local i files="$prefix/APKBUILD"
	for i in $source; do
		files="$files $prefix/${i##*/}"
	done
	mkdir -p "$PKGDEST"
317
	(cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files) 
Natanael Copa's avatar
Natanael Copa committed
318 319
}

320 321
# check if package is up to date
up2date() {
322
	local pkg="$PKGDEST/$pkgname-$pkgver-$pkgrel.apk"
323
	local i s
Natanael Copa's avatar
Natanael Copa committed
324
	cd "$startdir"
325 326 327 328 329 330 331 332 333 334
	[ -f "$pkg" ] || return 1
	for i in $source APKBUILD; do
		local s="$SRCDEST/${i##*/}"	# $(basename $i)
		if [ "$s" -nt "$pkg" ]; then
			return 1
		fi
	done
	return 0
}

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
# note: this must run in a subshell
find_aport() {
	local i
	cd ../..
	for i in */*/APKBUILD; do
		. $i
		local j
		for j in $pkgname $subpackages; do
			if [ "${j%%:*}" = "$1" ]; then
				echo "$PWD/${i%/APKBUILD}/$1-$pkgver-r$pkgrel.apk"
				return 0
			fi
		done
	done
	return 1
}

# recursively build and install dependencies
builddeps() {
	local dep pkg
	for dep in $depends $makedepends; do
		apk_info -e $dep && continue
		[ -z "$recursive" ] && die "Missing dependency $dep. Use -r to build recursively"
		# sudo apk_add $dep && continue
		pkg=$(find_aport $dep) || die "failed to find dependency $dep"
		# recursively build deps
		msg "entering ${pkg%/*}"
		cd ${pkg%/*} 
		$0 -r || return 1
		sudo apk_add $pkg
	done
}

Natanael Copa's avatar
Natanael Copa committed
368 369 370 371 372 373
usage() {
	echo "$(basename $0) $myver"
	echo "usage: $0 [options] [cmd] ..."
	echo "Options:"
	echo " -h  Show this help"
	echo " -f  Force specified cmd, even if they are already done"
374
	echo " -r  Recursively build and install dependencies (using sudo)"
Natanael Copa's avatar
Natanael Copa committed
375 376 377
	echo " -q  Quiet"
	echo ""
	echo "Commands:"
378 379 380 381 382 383 384 385 386 387 388 389 390
	echo "  checksum    Generate checksum to be included in $APKBUILD"
	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"
	echo "  package     Create package in \$PKGDEST"
	echo "  rootpkg     Run '$0 build package' as fakeroot"
	echo "  clean       Remove temp build and install dirs"
	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"
Natanael Copa's avatar
Natanael Copa committed
391 392 393 394 395 396 397 398 399
	echo ""
	exit 0
}

checksum() {
	local s files
	for s in $source; do
		files="$files ${s##*/}"
	done
400 401
	md5sums="$(cd "$SRCDEST" && md5sum $files)" || die "md5sum failed"
	echo "md5sums=\"$md5sums\""
Natanael Copa's avatar
Natanael Copa committed
402 403 404 405
}

APKBUILD="${APKBUILD:-./APKBUILD}"

406
while getopts "hfqr" opt; do
Natanael Copa's avatar
Natanael Copa committed
407 408 409 410
	case $opt in
		'h') usage;;
		'f') force=1;;
		'q') quiet=1;;
411
		'r') recursive=1;;
Natanael Copa's avatar
Natanael Copa committed
412 413 414 415 416 417 418 419
	esac
done
shift $(( $OPTIND - 1 ))

# source the buildfile
[ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
. "$APKBUILD"

Natanael Copa's avatar
Natanael Copa committed
420
# If we are handling a sub package then reset subpackages
421 422 423
if [ -n "$subpkgname" ]; then
	subpackages=
fi
Natanael Copa's avatar
Natanael Copa committed
424 425 426 427 428 429 430

trap 'die "Aborted by user"' INT

[ -n "$forceunpack" ] && rm -f "$srcdir"/.unpack


if [ -z "$1" ]; then
Natanael Copa's avatar
Natanael Copa committed
431
	if up2date && [ -z "$force" ]; then
Natanael Copa's avatar
Natanael Copa committed
432
		msg "Package is up to date"
433 434 435
	else
		set $default_cmds
	fi
Natanael Copa's avatar
Natanael Copa committed
436 437 438 439 440 441 442
fi

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