Newer
Older
#!/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,
#
startdir="$PWD"
srcdir=${srcdir:-"$startdir/src"}
pkgdir=${pkgdir:-"$startdir/pkg"}
pkgrel=0
# defaults
SRCDEST=${SRCDEST:-$startdir}
PKGDEST=${PKGDEST:-$startdir}
BUILD_BASE="binutils gcc make patch uclibc-dev"
default_cmds="sanitycheck builddeps clean fetch unpack rootpkg"
# read config
ABUILD_CONF=${ABUILD_CONF:-"/etc/abuild.conf"}
[ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF"
# If REPODEST is set then it will override the PKGDEST
if [ -n "$REPODEST" ]; then
PKGDEST="$REPODEST/$repo"
fi
# source functions
# if abuild was not run from PATH, then look for func lib at same location
if [ -z "$FUNCLIB" ]; then
FUNCLIB="${0##/*}/functions.sh"
[ -f "$FUNCLIB" ] || FUNCLIB=/usr/share/abuild/functions.sh
fi
if ! [ -f "$FUNCLIB" ]; then
echo "$FUNCLIB: not found" >&2
exit 1
fi
. "$FUNCLIB"
if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then
# check if apkbuild is basicly sane
sanitycheck() {
msg "Checking sanity of $APKBUILD..."
[ -z "$pkgname" ] && die "Missing pkgname in APKBUILD"
[ -z "${pkgname##* *}" ] && die "pkgname contains spaces"
[ -z "$pkgver" ] && die "Missing pkgver in APKBUILD"
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"
if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
die "Number of md5sums does not correspond to number of sources"
fi
# 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() {
if [ -z "$source" ]; then
return 0
fi
if [ -z "$md5sums" ]; then
die "Use 'abuild checksum' to generate/update the checksum(s)"
if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then
die "Number of md5sums does not correspond to number of sources"
fi
msg "Checking md5sums..."
cd "$srcdir" && echo "$md5sums" | md5sum -c
}
uri_fetch() {
local uri="$1"
local d="${s##*/}" # $(basename $s)
local opts
[ -n "$quiet" ] && opts="-q"
[ -f "$SRCDEST/$d" ] && return 0
if [ -f "$SRCDEST/$d.part" ]; then
msg "Partial download found. Trying to resume"
opts="$opts -c"
wget $opts -O "$SRCDEST/$d.part" "$uri" \
&& mv "$SRCDEST/$d.part" "$SRCDEST/$d"
is_remote() {
case "$1" in
http://*|ftp://*)
return 0;;
esac
return 1
}
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
done
}
# unpack the sources
unpack() {
local u
mkdir -p "$srcdir"
for u in $source; do
local s="$SRCDEST/${u##*/}" # $(basename $s)
case "$s" in
*.tar.lzma)
msg "Unpacking $s..."
unlzma -c "$s" | tar -C "$srcdir" -x \
|| return 1;;
*.zip)
msg "Unpacking $s..."
unzip "$s" -d "$srcdir" || return 1;;
esac
done
}
# cleanup source and package dir
clean() {
msg "Cleaning temporary build dirs..."
for i in $subpackages; do
rm -rf "$pkgdir-$(get_split_func $i)"
done
}
# cleanup fetched sources
cleancache() {
local s
for s in $source; do
if is_remote "$s"; then
msg "Cleaning downloaded ${s##*/}..."
rm -f "$SRCDEST/${s##*/}"
fi
msg "Cleaning built packages..."
for i in $pkgname $subpackages; do
local p="$i-$pkgver-r$pkgrel"
rm -f "$PKGDEST/$p.apk" "$PKGDEST/$p.src.tar.gz"
# 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
}
[ -n "$DEBUG" ] && msg "$part"
$part || die "$part failed"
}
# override those in your build script
build() {
die "No build() function found in $APKBUILD"
}
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
}
local func=$(get_split_func $i)
# call abuild recursively, setting subpkg{dir,name}
msg "Running split function $func..."
subpkgdir="$startdir/pkg-$func" subpkgname="${i%:*}" \
local name=${subpkgname:-$pkgname}
[ -z "${name##* *}" ] && die "package name contains spaces"
local pkg="$name-$pkgver-r$pkgrel.apk"
[ ! -d "$dir" ] && die "Missing $dir"
cd "$dir"
msg "Creating ${subpkgname:+sub}package $pkg..."
local builddate=$(date -u "+%s")
local size=$(du -sk | awk '{print $1 * 1024}')
echo "# Generated by $(basename $0) $abuild_ver" >.PKGINFO
if [ -n "$FAKEROOTKEY" ]; then
echo "# using $(fakeroot -v)" >> .PKGINFO
fi
echo "# $(date -u)" >> .PKGINFO
cat >> .PKGINFO <<EOF
pkgdesc = $pkgdesc
url = $url
builddate = $builddate
packager = ${PACKAGER:-"Unknown"}
size = $size
EOF
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"
if [ -n "$install" ]; then
cp "$srcdir/$install" "$dir/.INSTALL" || return 1
chmod +x "$dir/.INSTALL"
# 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 $@ )
depends="$depends_doc"
if [ -d "$pkgdir/usr/share/$i" ]; then
mkdir -p "$subpkgdir/usr/share"
mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/"
rm -f "$subpkgdir/usr/share/info/dir"
# # compress info and man pages
# find "$subpkgdir/usr/share" \( -name '*.info' -o -name '*.info-[1-9]' \
# -o -name '*.[1-9]' \) -exec gzip {} \;
# remove if empty, ignore error (not empty)
rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null
# [ -d "$subpkgdir/usr/share/man" ] && depends="man"
depends="$kernel $depends_mod"
if [ -d "$pkgdir/lib/$i" ]; then
rm -rf "$subpkgdir/lib"
mkdir -p "$subpkgdir/lib"
mv "$pkgdir/lib/$i" "$subpkgdir/lib"
depends="$pkgname $depends_dev"
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
if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
d="$subpkgdir/${i%/*}" # dirname $i
rmdir "$pkgdir/${i%/*}" 2>/dev/null
}
# build and package in fakeroot
rootpkg() {
msg "Entering fakeroot..."
fakeroot $0 build subpkg package
}
srcpkg() {
local p="$pkgname-$pkgver-$pkgrel"
local i files="$prefix/APKBUILD"
for i in $source; do
files="$files $prefix/${i##*/}"
done
mkdir -p "$PKGDEST"
msg "Creating source package $p.src.tar.gz..."
(cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files)
# check if package is up to date
up2date() {
local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk"
for i in $pkgname $subpackages; do
[ -f "$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" ] || return 1
done
[ -n "$keep" ] && return 0
for i in $source APKBUILD; do
local s
if is_remote "$i"; then
s="$SRCDEST/${i##*/}" # $(basename $i)
else
s="$startdir/${i##*/}"
fi
if [ "$s" -nt "$pkg" ]; then
return 1
fi
done
return 0
}
# 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=
for j in $pkgname $subpackages; do
echo "o ${j%%:*} $dir"
set -- $depends $makedepends
echo -n "d ${j%%:*} $1"
shift
while [ $# -gt 0 ]; do
echo -n ",$1"
shift
done
echo
deptrace() {
( depparse_aports
if [ -z "$upgrade" ]; then
# list installed pkgs and prefix with 'i '
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
) | awk -v pkgs="$BUILD_BASE $depends $makedepends" '
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() {
local deps alldeps pkg i dir ver
msg "Building dependencies..."
deps="$BUILD_BASE $depends $makedepends"
if [ -z "$recursive" ]; then
for i in $deps; do
apk info -e $i || die "Missing dependency $i. Use -r to build recursively"
done
return 0
fi
for i in $(deptrace); do
# i = pkg:dir
local dir=${i#*:}
local pkg=${i%:*}
msg "Entering $dir"
cd "$dir" || return 1
$0 -i $pkg || return 1
uninstall_after="$pkg $uninstall_after"
# replace the md5sums in the APKBUILD
msg "Updating the md5sums in APKBUILD..."
for s in $source; do
files="$files ${s##*/}"
done
md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
cd "${subpkgdir:-$pkgdir}" || return 1
msg "Stripping binaries"
find . -type f 2>/dev/null | while read bin; do
local opt=
case "$(file -biz "$bin")" in
*/x-sharedlib*|*/x-archive*)
strip --strip-debug "$bin";;
*/x-executable*)
strip "$bin";;
esac
done
return 0
}
# simply list target apks
listpkg() {
local i
for i in $pkgname $subpackages; do
echo "${i%:*}-$pkgver-r$pkgrel.apk"
done
}
subpackages_has() {
local i
for i in $subpackages; do
[ "$1" = "${i%:*}" ] && return 0
done
return 1
}
# 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
sudo apk add -u "$pkgf" || die "Failed to install $1"
}
echo "$(basename $0) $abuild_ver"
echo "usage: $0 [options] [-i PKG] [-p PKGDEST] [-s SRCDEST] [cmd] ..."
echo "Options:"
echo " -f Force specified cmd, even if they are already done"
echo " -h Show this help"
echo " -i Install PKG after successul build"
echo " -k Keep built packages, even if APKBUILD or sources are newer"
echo " -p Set package destination directory"
echo " -r Recursively build and install missing dependencies (using sudo)"
echo " -s Set source package destination directory"
echo " -u Recursively build and upgrade dependencies (using sudo)"
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 " listpkg List target packages"
echo " package Create package in \$PKGDEST"
echo " rootpkg Run '$0 build package' as fakeroot"
echo " clean Remove temp build and install dirs"
echo " cleanoldpkg Remove binary packages except current version"
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"
echo ""
exit 0
}
APKBUILD="${APKBUILD:-./APKBUILD}"
while getopts "fhi:kip:qrs:u" opt; do
'h') usage;;
'i') install_after="$install_after $OPTARG";;
'p') PKGDEST=$OPTARG;;
's') SRCDEST=$OPTARG;;
'u') upgrade=1
recursive=1;;
# source the buildfile
[ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)"
. "$APKBUILD"
# If we are handling a sub package then reset subpackages
if [ -n "$subpkgname" ]; then
subpackages=
fi
else
set $default_cmds
fi
fi
while [ $# -gt 0 ]; do
runpart $1
shift
done