#!/bin/sh # script to build apk packages (light version of makepkg) # Copyright (c) 2008 Natanael Copa # # Distributed under GPL-2 # # Depends on: busybox utilities, fakeroot, # abuild_ver=@VERSION@ sysconfdir=@sysconfdir@ abuildrepo=@abuildrepo@ datadir=@datadir@ program=${0##*/} abuild_path=$(readlink -f $0) # defaults BUILD_BASE="build-base" SUDO=${SUDO:-"sudo"} FAKEROOT=${FAKEROOT:-"fakeroot"} APK=${APK:-apk} # read config ABUILD_CONF=${ABUILD_CONF:-"$sysconfdir/abuild.conf"} [ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF" default_colors() { NORMAL="\033[1;0m" STRONG="\033[1;1m" RED="\033[1;31m" GREEN="\033[1;32m" YELLOW="\033[1;33m" BLUE="\033[1;34m" } monochrome() { NORMAL="" STRONG="" RED="" GREEN="" YELLOW="" BLUE="" } #colors if [ -n "$USE_COLORS" ]; then default_colors 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 } set_xterm_title() { if [ "$TERM" = xterm ]; then printf "\033]0;$1\007" >&2 fi } cleanup() { set_xterm_title "" if [ -z "$install_after" ] && [ -n "$uninstall_after" ]; then $SUDO $APK del $uninstall_after fi } die() { error "$@" cleanup exit 1 } # check if apkbuild is basicly sane sanitycheck() { local i 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" if [ "$pkgver" != "volatile" ] && [ -z "$nodeps" ]; then $APK version --check -q "$pkgver" ||\ die "$pkgver is not a valid version" fi [ -z "$pkgrel" ] && die "Missing pkgrel in APKBUILD" [ -z "$pkgdesc" ] && die "Missing pkgdesc in APKBUILD" [ -z "$url" ] && die "Missing url in APKBUILD" [ -z "$license" ] && die "Missing license in APKBULID" for i in $install; do [ -e "$startdir/$i" ] || die "install script $startdir/$i is missing" done [ -n "${triggers%%:*}" ] && [ ! -e "$startdir"/${triggers%%:*} ] \ && die "trigger script $startdir/${triggers%%:*} is missing" if [ -n "$source" ]; then for i in $source; do if install_has "$i"; then warning "You should not have \$install in source" continue fi md5sums_has ${i##*/} || die "${i##*/} is missing in md5sums" case "$i" in https://*) makedepends_has wget || die "wget must be in makedepends when source has https://" ;; esac done fi if [ -n "$md5sums" ]; then for i in $(echo "$md5sums" | awk '{ print $2 }'); do source_has $i || die "$i exists in md5sums but is missing in source" done fi # common spelling errors [ -n "$depend" ] && die "APKBUILD contains 'depend'. It should be depends" [ -n "$makedepend" ] && die "APKBUILD contains 'makedepend'. It should be makedepends" grep '^# Maintainer:' $APKBUILD >/dev/null || warning "No maintainer" makedepends_has 'g++' && warning "g++ should not be in makedepends" return 0 } md5check() { local dummy f if [ -z "$source" ]; then return 0 fi if [ -z "$md5sums" ]; then die "Use 'abuild checksum' to generate/update the checksum(s)" fi if [ "$(echo $source | wc -l)" -ne "$(echo $md5sums | wc -l)" ]; then die "Number of md5sums does not correspond to number of sources" fi fetch || return 1 msg "Checking md5sums..." cd "$srcdir" && echo "$md5sums" | md5sum -c } uri_fetch() { local uri="$1" local d="${uri##*/}" # $(basename $uri) local opts [ -n "$quiet" ] && opts="-q" [ -f "$SRCDEST/$d" ] && return 0 # we need GNU wget for this case "$uri" in https://*) opts="--no-check-certificate";; esac mkdir -p "$SRCDEST" if [ -f "$SRCDEST/$d.part" ]; then msg "Partial download found. Trying to resume" opts="$opts -c" fi msg "Fetching $uri" wget $opts -O "$SRCDEST/$d.part" "$uri" \ && mv "$SRCDEST/$d.part" "$SRCDEST/$d" } is_remote() { case "$1" in http://*|ftp://*|https://*) return 0;; esac return 1 } # try download from file from mirror first uri_fetch_mirror() { local uri="$1" local d="${uri##*/}" # $(basename $uri) if [ -n "$DISTFILES_MIRROR" ]; then if is_remote "$DISTFILES_MIRROR"; then uri_fetch "$DISTFILES_MIRROR"/$d && return 0 else cp "$DISTFILES_MIRROR"/$d "$SRCDEST" && return 0 fi fi uri_fetch "$uri" } default_fetch() { local s mkdir -p "$srcdir" for s in $source; do if is_remote "$s"; then uri_fetch_mirror "$s" || return 1 ln -sf "$SRCDEST/${s##*/}" "$srcdir"/ else ln -sf "$startdir/$s" "$srcdir/" fi done } fetch() { default_fetch } # unpack the sources default_unpack() { local u md5check || return 1 mkdir -p "$srcdir" for u in $source; do local s="$SRCDEST/${u##*/}" # $(basename $s) case "$s" in *.tar.gz|*.tgz) msg "Unpacking $s..." tar -C "$srcdir" -zxf "$s" || return 1;; *.tar.bz2) msg "Unpacking $s..." tar -C "$srcdir" -jxf "$s" || return 1;; *.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 } unpack() { default_unpack } # cleanup source and package dir clean() { msg "Cleaning temporary build dirs..." rm -rf "$srcdir" rm -rf "$pkgbasedir" } # 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 done } cleanpkg() { local i getpkgver || return 1 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" \ "$abuildrepo"/$p.apk done # remove given packages from index } # clean all packages except current cleanoldpkg() { local i j getpkgver || return 1 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 } mkusers() { local i for i in $pkgusers; do if ! getent passwd $i >/dev/null; then msg "Creating user $i" $SUDO adduser -D -H $i || return 1 fi done for i in $pkggroups; do if ! getent group $i >/dev/null; then msg "Creating group $i" $SUDO addgroup $i || return 1 fi done } runpart() { local part=$1 [ -n "$DEBUG" ] && msg "$part" $part || die "$part failed" } # override those in your build script getpkgver() { # this func is supposed to be overridden by volatile packages if [ "$pkgver" = "volatile" ]; then error "Please provide a getpkgver() function in your APKBUILD" return 1 fi } prepare() { : } build() { : } # generate a simple tar.gz package of pkgdir targz() { cd "$pkgdir" || return 1 tar -czf "$PKGDEST"/$pkgname-$pkgver-r$pkgrel.tar.gz * } 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 } prepare_subpackages() { if [ -z "$subpackages" ]; then return 0 fi local i cd "$startdir" for i in $subpackages; do local func=$(get_split_func $i) # call abuild recursively, setting subpkg{dir,name} msg "Running split function $func..." subpkgdir="$pkgbasedir/${i%:*}" subpkgname="${i%:*}" \ $0 $func prepare_package || return 1 done } prepare_metafiles() { getpkgver || return 1 local name=${subpkgname:-$pkgname} [ -z "${name##* *}" ] && die "package name contains spaces" local dir=${subpkgdir:-$pkgdir} local pkg="$name-$pkgver-r$pkgrel.apk" local pkginfo="$controldir"/.PKGINFO local sub [ ! -d "$dir" ] && die "Missing $dir" cd "$dir" mkdir -p "$controldir" 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" </dev/null ; then msg "Script found. busybox added as a dependency for $pkg" deps="$deps busybox" break fi done fi for i in $license; do echo "license = $i" >> "$pkginfo" done for i in $replaces; do echo "replaces = $i" >> "$pkginfo" done for i in $deps; 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 if [ -n "$triggers" ]; then echo "triggers = ${triggers#*:}" >> "$pkginfo" fi local metafiles=".PKGINFO" for i in $install ${triggers%%:*}; do script=${i#$name} case "$script" in .pre-install|.post-install|.pre-upgrade|.post-upgrade|.pre-deinstall|.post-deinstall|.trigger) msg "Adding $script" ;; *) error "$script: Invalid install/trigger script" return 1 ;; esac cp "$startdir/$i" "$controldir/$script" || return 1 chmod +x "$controldir/$script" metafiles="$metafiles $script" done echo $metafiles | tr ' ' '\n' > "$controldir"/.metafiles } prepare_tracedeps() { local dir=${subpkgdir:-$pkgdir} options_has "!tracedeps" && return 0 find -name '*.so' -o -name '*.so.[0-9]*' | sed 's:.*/::' \ >"$controldir"/.provides-so scanelf -Rn "$dir" | awk -F "\ " '$1 == "ET_DYN" || $1 == "ET_EXEC" {print $2}' \ | sed 's:,:\n:g' | sort | uniq \ | while read i; do # only add files that are not self provided grep "^$i$" "$controldir"/.provides-so >/dev/null \ || echo $i >> "$controldir"/.needs-so done } prepare_package() { msg "Preparing ${subpkgname:+sub}package ${subpkgname:-$pkgname}..." stripbin prepare_metafiles && prepare_tracedeps } pkginfo_val() { local key="$1" local file="$2" awk -F ' = ' "\$1 == \"$key\" {print \$2}" "$file" } trace_apk_deps() { local name="$1" local dir="$2" local i j found autodeps= msg "Tracing dependencies for $name..." # add pkgconfig if usr/lib/pkgconfig is found if [ -d "$pkgbasedir"/$name/usr/lib/pkgconfig ] \ && ! grep -q '^depend = pkgconfig' "$dir"/.PKGINFO; then msg "Added pkgconfig as dependency" echo "depend = pkgconfig" >> "$dir"/.PKGINFO fi for i in $(cat "$dir"/.needs-so 2>/dev/null); do found= # first check if its provide by same apkbuild for j in "$dir"/../.control.*/.provides-so; do grep -w "$i" "$j" >/dev/null || continue found=${j%/.provides-so} found=${found##*/.control.} break done # check apk db if not provided by a subpackage if [ -z "$found" ]; then found=$($APK info -q -W /lib/$i /usr/lib/$i) fi if [ -z "$found" ]; then error "Could not find dependency for $i" return 1 fi if grep -w "^depend = ${found}$" "$dir"/.PKGINFO >/dev/null ; then warning "You can remove '$found' from depends" continue fi list_has "$found" $autodeps || autodeps="$autodeps $found" msg "Added '$found' as dependency as it has $i" done [ -z "$autodeps" ] && return 0 echo "# automatically detected:" >> "$dir"/.PKGINFO for i in $autodeps; do echo "depend = $i" >> "$dir"/.PKGINFO done } create_apks() { local file getpkgver || return 1 for file in "$pkgbasedir"/.control.*/.PKGINFO; do local dir="${file%/.PKGINFO}" local name=$(pkginfo_val pkgname $file) local ver=$(pkginfo_val pkgver $file) local apk=$name-$ver.apk local datadir="$pkgbasedir"/$name trace_apk_deps "$name" "$dir" || return 1 msg "Creating $apk..." ( cd "$datadir" # data.tar.gz set -- * if [ "$1" = '*' ]; then touch .dummy set -- .dummy fi tar -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz # append the hash for data.tar.gz local sha256=$(sha256sum "$dir"/data.tar.gz | cut -f1 -d' ') echo "datahash = $sha256" >> "$dir"/.PKGINFO # control.tar.gz cd "$dir" tar -c $(cat "$dir"/.metafiles) | abuild-tar --cut \ | gzip -9 > control.tar.gz abuild-sign -q control.tar.gz || exit 1 # create the final apk cat control.tar.gz data.tar.gz > "$PKGDEST"/$apk ) done } update_abuildrepo() { if ! apk_up2date || [ -n "$force" ]; then sanitycheck && builddeps && clean && fetch && unpack \ && prepare && mkusers && rootpkg || return 1 fi local apk mkdir -p "$abuildrepo" || return 1 cd "$abuildrepo" # remove broken links for apk in *.apk; do if [ -L "$apk" ] && [ ! -f "$apk" ]; then rm -f "$apk" fi done # create links for this package for apk in $(listpkg); do ln -sf "$PKGDEST"/$apk "$abuildrepo"/$apk done msg "Updating the cached abuild repository index..." local sign=".SIGN.RSA.${SIGN_PUBLIC_KEY##*/}" local oldindex= if [ -f APKINDEX.tar.gz ]; then oldindex="--index APKINDEX.tar.gz" fi $APK index $oldindex --output APKINDEX.tar.gz.unsigned \ --description "$repo $(cd $startdir && git describe)" \ *.apk || exit 1 msg "Signing the index..." abuild-sign -q APKINDEX.tar.gz.unsigned || exit 1 mv APKINDEX.tar.gz.unsigned APKINDEX.tar.gz chmod 644 APKINDEX.tar.gz } # predefined splitfunc doc default_doc() { depends="$depends_doc" install="$install_doc" triggers="$triggers_doc" local i for i in doc man info html sgml licenses gtk-doc; do if [ -d "$pkgdir/usr/share/$i" ]; then mkdir -p "$subpkgdir/usr/share" mv "$pkgdir/usr/share/$i" "$subpkgdir/usr/share/" fi done 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" return 0 } doc() { default_doc } # predefined splitfunc mod default_mod() { depends="$kernel $depends_mod" install="$install_mod" for i in firmware modules; do if [ -d "$pkgdir/lib/$i" ]; then rm -rf "$subpkgdir/lib" mkdir -p "$subpkgdir/lib" mv "$pkgdir/lib/$i" "$subpkgdir/lib" fi done } mod() { default_mod } # predefined splitfunc dev default_dev() { local i= j= depends="$pkgname $depends_dev" install="$install_dev" triggers="$triggers_dev" for i in $origsubpackages; do [ "${i%:*}" = "$subpkgname" ] || depends="$depends ${i%:*}" done cd "$pkgdir" || return 0 for i in usr/include usr/lib/pkgconfig usr/share/aclocal\ usr/share/gettext usr/bin/*-config \ usr/share/vala/vapi usr/share/gir-[0-9]*\ $(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 mkdir -p "$d" mv "$pkgdir/$i" "$d" rmdir "$pkgdir/${i%/*}" 2>/dev/null fi done # move *.so links needed when linking the apps to -dev packages for i in lib/*.so usr/lib/*.so; do if [ -L "$i" ]; then mkdir -p "$subpkgdir"/"${i%/*}" mv "$i" "$subpkgdir/$i" || return 1 fi done return 0 } dev() { default_dev } is_function() { type "$1" 2>&1 | head -n 1 | egrep -q "is a (shell )?function" } # build and package in fakeroot rootpkg() { local do_build=build cd "$startdir" if is_function package; then build || return 1 do_build=package fi cd "$startdir" [ -n "$FAKEROOT" ] && msg "Entering fakeroot..." $FAKEROOT -- "$abuild_path" $color_opt $do_build \ prepare_subpackages \ prepare_package \ create_apks } srcpkg() { getpkgver || return 1 local p="$pkgname-$pkgver-$pkgrel" local prefix="${startdir##*/}" 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 apk_up2date() { getpkgver || return 1 local pkg="$PKGDEST/$pkgname-$pkgver-r$pkgrel.apk" local i s cd "$startdir" 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 } abuildindex_up2date() { local i apk getpkgver || return 1 for i in $pkgname $subpackages; do apk="${i%:*}-$pkgver-r$pkgrel.apk" [ "$abuildrepo"/APKINDEX.tar.gz -nt "$abuildrepo"/$apk ] || return 1 done return 0 } up2date() { apk_up2date && abuildindex_up2date } # rebuild package and abuildrepo index if needed abuildindex() { up2date && return 0 update_abuildrepo } # 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= . $i dir=${i%/APKBUILD} deps= # filter out conflicts from deps and version info for j in $depends $makedepends; do case "$j" in !*) continue;; esac deps="$deps ${j%%[<>=]*}" done for j in $pkgname $subpackages; do echo "o ${j%%:*} $dir" set -- $deps echo -n "d ${j%%:*} $1" shift while [ $# -gt 0 ]; do echo -n ",$1" shift done echo done done ) } deptrace() { local deps= i= # strip versions from deps for i in "$@"; do deps="$deps ${i%%[<>=]*}" done [ -z "$deps" ] && return 0 ( depparse_aports if [ -z "$upgrade" ]; then # list installed pkgs and prefix with 'i ' $APK info -q | sort | sed 's/^/i /' fi ) | awk -v pkgs="$deps" ' 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= missing= installed_deps= local filtered_deps= conflicts= [ -n "$nodeps" ] && return 0 msg "Analyzing dependencies..." # add depends unless it is a subpackage or package itself for i in $BUILD_BASE $depends $makedepends; do [ "$pkgname" = "${i%%[<>=]*}" ] && continue subpackages_has ${i%%[<>=]*} || deps="$deps $i" done installed_deps=$($APK info -e $deps) # find which deps are missing for i in $deps; do if [ "${i#\!}" != "$i" ]; then $APK info -q -e "${i#\!}" \ && conflicts="$conflicts ${i#\!}" elif ! deplist_has $i $installed_deps || [ -n "$upgrade" ]; then missing="$missing $i" fi done if [ -n "$conflicts" ]; then error "Conflicting package(s) installed:$conflicts" return 1 fi if [ -z "$install_deps" ] && [ -z "$recursive" ]; then # if we dont have any missing deps we are done now [ -z "$missing" ] && return 0 error "Missing dependencies: $missing Use -r to autoinstall or -R to build" return 1 fi uninstall_after=".makedepends-$pkgname $uninstall_after" if [ -n "$install_deps" ] && [ -z "$recursive" ]; then # make a --simluate run first to detect missing deps # apk-tools --virtual is no goot at reporting those. $SUDO $APK add --repository "$abuildrepo" \ --wait 30 \ --simulate --quiet $deps || return 1 $SUDO $APK add --repository "$abuildrepo" \ --wait 30 \ --virtual .makedepends-$pkgname $deps \ && return 0 fi [ -z "$recursive" ] && return 1 # find dependencies that are installed but missing in repo. for i in $deps; do local m=$($APK search --repository "$abuildrepo" ${i%%[<>=]*}) if [ -z "$m" ]; then missing="$missing $i" fi done for i in $(deptrace $missing); do # i = pkg:dir local dir=${i#*:} local pkg=${i%:*} # ignore if dependency is in other repo [ -d "$dir" ] || continue # break cricular deps list_has $pkg $ABUILD_VISITED && continue export ABUILD_VISITED="$ABUILD_VISITED $pkg" msg "Entering $dir" cd "$dir" && $0 $forceroot $keep $quiet $install_deps \ $recursive $upgrade $color_opt abuildindex || return 1 done $SUDO $APK add -u --repository "$abuildrepo" \ --wait 30 \ --virtual .makedepends-$pkgname $deps } # replace the md5sums in the APKBUILD checksum() { local s files [ -z "$source" ] && return 0 fetch 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" } stripbin() { local bin options_has "!strip" && return 0 cd "${subpkgdir:-$pkgdir}" || return 1 msg "Stripping binaries" scanelf --recursive --nobanner --etype "ET_DYN,ET_EXEC" . \ | sed -e 's:^ET_DYN ::' -e 's:^ET_EXEC ::' \ | xargs -r strip } # simply list target apks listpkg() { local i getpkgver || return 1 for i in $pkgname $subpackages; do echo "${i%:*}-$pkgver-r$pkgrel.apk" done } source_has() { local i for i in $source; do [ "$1" = "${i##*/}" ] && return 0 done return 1 } subpackages_has() { local i for i in $subpackages; do [ "$1" = "${i%:*}" ] && return 0 done return 1 } list_has() { local needle="$1" local i shift for i in $@; do [ "$needle" = "$i" ] && return 0 [ "$needle" = "!$i" ] && return 1 done return 1 } # same as list_has but we filter version info deplist_has() { local needle="$1" local i shift for i in $@; do i=${i%%[<>=]*} [ "$needle" = "$i" ] && return 0 [ "$needle" = "!$i" ] && return 1 done return 1 } options_has() { list_has "$1" $options } depends_has() { deplist_has "$1" $depends } makedepends_has() { deplist_has "$1" $makedepends } md5sums_has() { list_has "$1" $md5sums } install_has() { list_has "$1" $install } # install package after build post_add() { getpkgver || return 1 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 --wait 30 -u "$pkgf" || die "Failed to install $1" } installdeps() { local deps i sudo $APK add --wait 30 --repository "$abuildrepo" \ --virtual .makedepends-$pkgname \ $makedepends } uninstalldeps (){ sudo $APK del .makedepends-$pkgname } all() { if up2date && [ -z "$force" ]; then msg "Package is up to date" else update_abuildrepo fi } usage() { echo "$program $abuild_ver" echo "usage: $program [options] [-i PKG] [-P REPODEST] [-p PKGDEST]" echo " [-s SRCDEST] [cmd] ..." echo " $program [-c] -n PKGNAME[-PKGVER]" echo "Options:" echo " -c Enable colored output" echo " -d Disable dependency checking" echo " -f Force specified cmd, even if they are already done" echo " -F Force run as root" 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 " -m Disable colors (monochrome)" echo " -p Set package destination directory" echo " -P Set PKGDEST to REPODEST/, where repo is the parents dir name" echo " -q Quiet" echo " -r Install missing dependencies from system repository (using sudo)" echo " -R Recursively build and install missing dependencies (using sudo)" echo " -s Set source package destination directory" echo " -u Recursively build and upgrade all dependencies (using sudo)" echo "" echo "Commands:" 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 " installdeps Install packages listed in makedepends and depends" echo " uninstalldeps Uninstall packages listed in makedepends and depends" echo "" exit 0 } APKBUILD="${APKBUILD:-./APKBUILD}" unset force unset recursive while getopts "cdfFhi:kimnp:P:qrRs:u" opt; do case $opt in 'c') default_colors color_opt="-c";; 'd') nodeps=1;; 'f') force="-f";; 'F') forceroot="-F";; 'h') usage;; 'i') install_after="$install_after $OPTARG";; 'k') keep="-k";; 'm') monochrome color_opt="-m";; 'n') die "Use newapkbuild to create new aports";; 'p') PKGDEST=$OPTARG;; 'P') REPODEST=$OPTARG;; 'q') quiet="-q";; 'r') install_deps="-r";; 'R') recursive="-R";; 's') SRCDEST=$OPTARG;; 'u') upgrade="-u" recursive="-R";; esac done shift $(( $OPTIND - 1 )) # check so we are not root if [ "$(whoami)" = "root" ] && [ -z "$FAKEROOTKEY" ]; then [ -z "$forceroot" ] && die "Do not run abuild as root" SUDO= FAKEROOT= fi # find startdir [ -f "$APKBUILD" ] || die "Could not find $APKBUILD (PWD=$PWD)" APKBUILD=$(readlink -f "$APKBUILD") startdir="${APKBUILD%/*}" srcdir=${srcdir:-"$startdir/src"} pkgbasedir=${pkgbasedir:-"$startdir/pkg"} pkgrel=0 repo=${startdir%/*} repo=${repo##*/} SRCDEST=${SRCDEST:-$startdir} PKGDEST=${PKGDEST:-$startdir} cd "$startdir" || die . "$APKBUILD" # If REPODEST is set then it will override the PKGDEST if [ -n "$REPODEST" ]; then PKGDEST="$REPODEST/$repo" fi # If we are handling a sub package then reset subpackages and install if [ -n "$subpkgname" ]; then origsubpackages="$subpackages" subpackages= install= fi pkgdir="$pkgbasedir/$pkgname" controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname} trap 'die "Aborted by user"' INT set_xterm_title "abuild: $pkgname" if [ -z "$1" ]; then set all fi while [ $# -gt 0 ]; do runpart $1 shift done for i in $install_after; do post_add $i done cleanup