Newer
Older
echo "$paths"
}
scan_shared_objects() {
local name="$1" controldir="$2" datadir="$3"
# allow spaces in paths
IFS=:
set -- $(find_scanelf_paths "$datadir")
unset IFS
if options_has "ldpath-recursive"; then
opt="--recursive"
fi
msg "Scanning shared objects"
# lets tell all the .so files this package provides in .provides-so
scanelf --nobanner --soname $opt "$@" | while read etype soname file; do
# if soname field is missing, soname will be the filepath
sover=0
if [ -z "$file" ]; then
file="$soname"
soname=${soname##*/}
fi
# we only want shared libs
case $soname in
*.so|*.so.[0-9]*);;
*) continue;;
esac
case "$file" in
*.so.[0-9]*) sover=${file##*.so.};;
*.so)
# filter out sonames with version when file does not
# have version
case "$soname" in
*.so.[0-9]*)
if options_has "sover-namecheck"; then
continue
fi
esac
;;
esac
echo "$soname $sover"
# use awk to filter out dupes that has sover = 0
done | awk '{ if (so[$1] == 0) so[$1] = $2; }
END { for (i in so) print(i " " so[i]); }' \
| sort -u > "$controldir"/.provides-so
# verify that we dont have any duplicates
local dupes="$(cut -d' ' -f1 "$controldir"/.provides-so | uniq -d)"
if [ -n "$dupes" ]; then
die "provides multiple versions of same shared object: $dupes"
fi
# now find the so dependencies
scanelf --nobanner --recursive --needed "$datadir" | tr ' ' ':' \
| awk -F ":" '$1 == "ET_DYN" || $1 == "ET_EXEC" {print $2}' \
| sed 's:,:\n:g' | sort -u \
# only add files that are not self provided
grep -q -w "^$soname" "$controldir"/.provides-so \
|| list_has "$soname" $somask \
|| echo $soname
done > "$controldir"/.needs-so
}
# read size in bytes from stdin and show as human readable
human_size() {
awk '{ split("B KB MB GB TB PB", type)
for(i=5; y < 1; i--)
y = $1 / (2**(10*i))
printf("%.1f %s\n", y, type[i+2]) }'
}
Natanael Copa
committed
create_apks() {
local file= dir= name= ver= apk= datadir= size=
getpkgver || return 1
if [ "$arch" != "noarch" ] && ! options_has "!tracedeps"; then
for file in "$pkgbasedir"/.control.*/.PKGINFO; do
dir="${file%/.PKGINFO}"
name="$(pkginfo_val pkgname $file)"
datadir="$pkgbasedir"/$name
subpkgname=$name
scan_shared_objects "$name" "$dir" "$datadir"
done
fi
for file in "$pkgbasedir"/.control.*/.PKGINFO; do
dir="${file%/.PKGINFO}"
name=$(pkginfo_val pkgname $file)
ver=$(pkginfo_val pkgver $file)
size=$(pkginfo_val size $file | human_size)
apk=$name-$ver.apk
datadir="$pkgbasedir"/$name
subpkgname=$name
trace_apk_deps "$name" "$dir" || return 1
msg "Package size: ${size}"
msg "Compressing data..."
Natanael Copa
committed
(
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
msg "Create checksum..."
# 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
tar -c $(cat "$dir"/.metafiles) | abuild-tar --cut \
| gzip -9 > control.tar.gz
abuild-sign -q control.tar.gz || exit 1
msg "Create $apk"
# create the final apk
cat control.tar.gz data.tar.gz > "$PKGDEST"/$apk
subpkgname=
cd "$abuildrepo" || return 1
# remove compat symlink
for d in "$abuildrepo/$CARCH"; do
[ -L "$d" ] && rm "$d"
done
# remove broken links from abuildrepo
for apk in *.apk */*.apk; do
if [ -L "$apk" ] && [ ! -f "$apk" ]; then
rm -f "$apk"
fi
done
[ -n "$REPODEST" ] && return 0
local apk
mkdir -p "$abuildrepo"/$CARCH
# create links for this package
[ -f "$PKGDEST"/$apk ] || continue
ln -sf "$PKGDEST"/$apk "$abuildrepo"/$CARCH/$apk
build_abuildrepo() {
local d apk
if ! apk_up2date || [ -n "$force" ]; then
sanitycheck && builddeps && clean && fetch && unpack \
&& prepare && mkusers && rootpkg || return 1
fi
update_abuildrepo_index
}
update_abuildrepo_index() {
clean_abuildrepo
mklinks_abuildrepo
cd "$abuildrepo"
local index=$CARCH/APKINDEX.tar.gz
msg "Updating the cached abuild repository index..."
local sign=".SIGN.RSA.${SIGN_PUBLIC_KEY##*/}"
local oldindex=
if [ -f "$index" ]; then
oldindex="--index $index"
$APK index --quiet $oldindex --output "$index".unsigned \
--description "$repo $(cd $startdir && git describe)" \
--rewrite-arch $CARCH \
$CARCH/*.apk || exit 1
abuild-sign -q "$index".unsigned || exit 1
mv "$index".unsigned "$index"
chmod 644 "$index"
default_doc() {
depends="$depends_doc"
pkgdesc="$pkgdesc (documentation)"
arch=${arch_doc:-"noarch"}
for i in doc man info html sgml licenses gtk-doc ri; do
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"
# remove if empty, ignore error (not empty)
rmdir "$pkgdir/usr/share" "$pkgdir/usr" 2>/dev/null
doc() {
default_doc
}
default_dev() {
depends="$pkgname $depends_dev"
pkgdesc="$pkgdesc (development files)"
for i in $origsubpackages; do
[ "${i%:*}" = "$subpkgname" ] || depends="$depends ${i%:*}"
done
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]' 2>/dev/null); do
if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
d="$subpkgdir/${i%/*}" # dirname $i
rmdir "$pkgdir/${i%/*}" 2>/dev/null
# 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
dev() {
default_dev
}
# predefined splitfunc libs
default_libs() {
pkgdesc="$pkgdesc (libraries)"
local dir= file=
for dir in lib usr/lib; do
for file in "$pkgdir"/$dir/lib*.so.[0-9]*; do
[ -f "$file" ] || continue
mkdir -p "$subpkgdir"/$dir
mv "$file" "$subpkgdir"/$dir/
done
done
}
libs() {
default_libs
}
is_function() {
type "$1" 2>&1 | head -n 1 | egrep -q "is a (shell )?function"
}
do_fakeroot() {
if [ -n "$FAKEROOT" ]; then
$FAKEROOT -- "$@"
else
"$@"
fi
}
local do_build=build
cd "$startdir"
if is_function package; then
build || return 1
[ -n "$FAKEROOT" ] && msg "Entering fakeroot..."
do_fakeroot "$abuild_path" $color_opt $do_build \
getpkgver || return 1
local p="$pkgname-$pkgver-$pkgrel"
local i files="$prefix/APKBUILD"
for i in $source; do
files="$files $prefix/$(filename_from uri $i)"
msg "Creating source package $p.src.tar.gz..."
(cd .. && tar -zcf "$PKGDEST/$p.src.tar.gz" $files)
# return true if arch is supported or noarch
check_arch() {
list_has $CARCH $arch || [ "$arch" = "noarch" ] || [ "$arch" = "all" ]
# check if package is up to date
getpkgver || return 1
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/$(filename_from_uri $i)"
else
s="$startdir/${i##*/}"
fi
if [ "$s" -nt "$pkg" ]; then
return 1
fi
done
return 0
}
getpkgver || return 1
local dir="$abuildrepo"/$CARCH
local apk="${pkgname%:*}-$pkgver-r$pkgrel.apk"
local idx="$dir"/APKINDEX.tar.gz
local file="$dir"/$apk
# check if index is missing
[ -f "$idx" ] || return 1
# if link or file is missing, then we need update abuildrepo index
[ -f "$file" ] || return 1
# if file exists and is newer than index, then we need update index
[ "$file" -nt "$idx" ] && return 1
return 0
}
up2date() {
apk_up2date && abuildindex_up2date
}
# rebuild package and abuildrepo index if needed
abuildindex() {
up2date && return 0
build_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=
# filter out conflicts from deps and version info
for j in $depends $makedepends; do
case "$j" in
!*) continue;;
esac
for j in $pkgname $subpackages; do
echo -n "d ${j%%:*} $1"
shift
while [ $# -gt 0 ]; do
echo -n ",$1"
shift
done
echo
local deps= i=
# strip versions from deps
for i in "$@"; do
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 /'
) | awk -v pkgs="$deps" '
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
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
Natanael Copa
committed
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" ] && [ -n "$deps" ]; then
# make a --simluate run first to detect missing deps
# apk-tools --virtual is no goot at reporting those.
$SUDO_APK add --repository "$abuildrepo" \
--simulate --quiet $deps || return 1
$SUDO_APK add --repository "$abuildrepo" \
--virtual .makedepends-$pkgname $deps \
&& return 0
[ -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%%[<>=]*})
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
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
$SUDO_APK add -u --repository "$abuildrepo" \
--virtual .makedepends-$pkgname $deps
# replace the md5sums in the APKBUILD
[ -z "$source" ] && [ -n "${md5sums}${sha256sums}${sha512sums}" ] \
&& msg "Removing checksums from APKBUILD"
sed -i -e '/^md5sums="/,/"\$/d; /^md5sums=''/,/''\$/d' "$APKBUILD"
sed -i -e '/^sha512sums="/,/"\$/d; /^sha512sums=''/,/''\$/d' "$APKBUILD"
sed -i -e '/^sha256sums="/,/"\$/d; /^sha256sums=''/,/''\$/d' "$APKBUILD"
[ -z "$source" ] && return 0
files="$files $(filename_from_uri $s)"
# for compatibility/backporting reasons we still add md5sum
msg "Updating the md5sums in APKBUILD..."
md5sums="$(cd "$srcdir" && md5sum $files)" || die "md5sum failed"
echo "md5sums=\"$md5sums\"" >>"$APKBUILD"
msg "Updating the sha256sums in APKBUILD..."
sha256sums="$(cd "$srcdir" && sha256sum $files)" \
|| die "sha256sum failed"
echo "sha256sums=\"$sha256sums\"" >>"$APKBUILD"
msg "Updating the sha512sums in APKBUILD..."
sha512sums="$(cd "$srcdir" && sha512sum $files)" \
|| die "sha512sum failed"
echo "sha512sums=\"$sha512sums\"" >>"$APKBUILD"
if options_has "!strip" || [ "$arch" = "noarch" ]; then
return 0
fi
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() {
getpkgver || return 1
for name in $(listpkgnames) ; do
echo "$name-$pkgver-r$pkgrel.apk"
source_has() {
local i
for i in $source; do
[ "$1" = "${i##*/}" ] && return 0
[ "$1" = "${i%%::*}" ] && return 0
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
[ "$needle" = "$i" ] && return 0
[ "$needle" = "!$i" ] && return 1
done
return 1
}
options_has() {
list_has "$1" $options
}
depends_has() {
deplist_has "$1" $depends
}
deplist_has "$1" $makedepends
md5sums_has() {
list_has "$1" $md5sums
}
install_has() {
list_has "$1" $install
}
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 $apk_opt_wait -u "$pkgf" || die "Failed to install $1"
installdeps() {
local deps i
$SUDO_APK add $apk_opt_wait --repository "$abuildrepo" \
--virtual .makedepends-$pkgname \
$makedepends
}
uninstalldeps (){
$SUDO_APK del $apk_opt_wait .makedepends-$pkgname
}
if ! [ -n "$force" ]; then
check_arch || return 0
fi
if up2date && [ -z "$force" ]; then
msg "Package is up to date"
else
build_abuildrepo
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
# This abuild hook will checkout an svn or git repository by specifying
# $svnurl or $giturl in APKBUILD. You can checkout a specific branch in
# git by adding -b $branch in $giturl. $reporev will select the correct
# commit, revision or tag for you. If you specify $disturl your distfile
# will automatically be uploaded with rsync to the url provided.
# Base version defaults to 0 except if specified by $basever.
snapshot() {
# check if we setup vars correctly
[ -z "$disturl" ] && warning "Missing disturl in APKBUILD, auto uploading disabled."
[ -z "$svnurl" ] && [ -z "$giturl" ] && die "Missding repository url in APKBUILD!"
[ -n "$svnurl" ] && [ -n "$giturl" ] && die "You can only use a single repository!"
local _date=$(date +%Y%m%d)
local _format="tar.gz"
# remove any repositories left in srcdir
abuild clean
mkdir -p "$srcdir" && cd "$srcdir"
# clone git repo and archive
if [ -n "$giturl" ]; then
local _version=${verbase:-0}_git${_date}
command -v git >/dev/null || \
die "Missing git! Install git to support git clone."
[ -z "$reporev" ] && local _rev="HEAD" && local _depth="--depth=1"
msg "Creating git snapshot: $pkgname-$_version"
git clone $_depth --bare $giturl $pkgname-$_version || return 1
git --git-dir $pkgname-$_version archive \
--format=$_format \
-o $pkgname-$_version.$_format \
--prefix=$pkgname-$_version/ $_rev \
|| return 1
fi
# export svn repo and archive
if [ -n "$svnurl" ]; then
local _version=${verbase:-0}_svn${_date}
command -v svn >/dev/null || \
die "Missing svn! Install subverion to support svn export."
[ -n "$reporev" ] && local _rev="-r $reporev"
msg "Creating svn snapshot: $pkgname-$_version"
svn export $_rev $svnurl $pkgname-$_version || return 1
tar zcf $pkgname-$_version.$_format $pkgname-$_version || return 1
fi
# upload to defined distfiles url
if [ -n "$disturl" ]; then
command -v rsync >/dev/null || \
die "Missing rsync! Install rsync to enable automatic uploads."
msg "Uploading to $disturl"
rsync --progress -La $pkgname-$_version.$_format \
$disturl || return 1
cd "$startdir"
# set the pkgver to current date and update checksum
sed -i -e "s/^pkgver=.*/pkgver=${_version}/" \
APKBUILD || return 1
abuild checksum
fi
}
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 " -c Enable colored output"
echo " -d Disable dependency checking"
echo " -f Force specified cmd, even if they are already done"
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/<repo>/\$CARCH, where repo is the parents dir name"
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 " 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 " verify Verify checksums"
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 " sourcecheck Check if remote source package exists upstream"
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 " snapshot Create a \$giturl or \$svnurl snapshot and upload to \$disturl"
echo ""
exit 0
}
APKBUILD="${APKBUILD:-./APKBUILD}"
while getopts "cdfFhi:kimnp:P:qrRs:u" opt; do
'c') default_colors
color_opt="-c";;
'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";;
# check so we are not root
if [ "$(whoami)" = "root" ] && [ -z "$FAKEROOTKEY" ]; then
[ -z "$forceroot" ] && die "Do not run abuild as root"
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/$CARCH"
# for recursive action
export REPODEST
abuildrepo="$REPODEST"/$repo
else
abuildrepo="$abuildrepo_base"/$repo
# if we want build debug package
if [ -n "$DEBUG" ]; then
CFLAGS="$CFLAGS -g"
options="$options !strip"
fi
# If we are handling a sub package then reset subpackages and install
origsubpackages="$subpackages"
controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname}
fi
while [ $# -gt 0 ]; do
runpart $1
shift
done