diff options
Diffstat (limited to 'abuild.in')
-rw-r--r-- | abuild.in | 363 |
1 files changed, 268 insertions, 95 deletions
@@ -1,7 +1,7 @@ #!/bin/sh # abuild - build apk packages (light version of makepkg) -# Copyright (c) 2008 Natanael Copa <natanael.copa@gmail.com> +# Copyright (c) 2008-2015 Natanael Copa <ncopa@alpinelinux.org> # # Distributed under GPL-2 # @@ -179,6 +179,16 @@ default_sanitycheck() { esac list_has ${i##*/} $md5sums $sha256sums $sha512sums \ || die "${i##*/} is missing in checksums" + + # verify that our source does not have git tag version + # name as tarball (typicallly github) + if is_remote "$i" && [ "${i#*::}" = "$i" ]; then + case ${i##*/} in + v$pkgver.tar.*|$pkgver.tar.*) + die "source ${i##*/} needs to be renamed to avoid possible collisions" + ;; + esac + fi done fi @@ -414,13 +424,20 @@ fetch() { # verify that all init.d scripts are openrc runscripts initdcheck() { - local i + local i line for i in $source; do case $i in - *.initd) - head -n 1 "$srcdir"/$i | grep -q '/sbin/runscript' \ - && continue - error "$i is not an openrc #!/sbin/runscript" + *.initd) line=$(head -n 1 "$srcdir"/$i);; + *) continue ;; + esac + + case "$line" in + *sbin/openrc-run) + ;; + *sbin/runscript) + warning "$i is not an openrc #!/sbin/openrc-run" + ;; + *) error "$i is not an openrc #!/sbin/openrc-run" return 1 ;; esac @@ -520,6 +537,7 @@ cleanoldpkg() { rm -f "$j" "$abuildrepo"/*/${j##*/} done done + update_abuildrepo_index return 0 } @@ -615,13 +633,12 @@ postcheck() { return 1 fi fi - # look for *.la files - i=$(find "$dir" -name '*.la' | sed "s|^$dir|\t|") - if [ -n "$i" ] && ! options_has "libtool"; then - error "Libtool archives (*.la) files found and \$options has no 'libtool' flag:" - echo "$i" - return 1 + + # remove *.la files if libtool is not set + if ! options_has "libtool"; then + find "$dir" -name '*.la' -type f -delete fi + # look for /usr/lib/charset.alias if [ -e "$dir"/usr/lib/charset.alias ] \ && ! options_has "charset.alias"; then @@ -634,7 +651,7 @@ postcheck() { warning "World writeable directories found:" echo "$i" fi - # check so we dont have any suid root binaries that are not + # check so we dont have any suid root binaries that are not PIE i=$(find "$dir" -type f -perm +6000 \ | xargs scanelf --nobanner --etype ET_EXEC \ | sed "s|ET_EXEC $dir|\t|") @@ -643,6 +660,17 @@ postcheck() { echo "$i" return 1 fi + # test suid bit on executable + if ! options_has "suid"; then + i=$(find "$dir" \( -perm -u+s -o -perm -g+s \) -a -type f \ + -a -perm -o+x) + if [ -n "$i" ]; then + error "Found executable files with SUID bit set:" + echo "$i" + return 1 + fi + fi + # test for textrels if ! options_has "textrels"; then local res="$(scanelf --recursive --textrel --quiet "$dir")" @@ -655,6 +683,15 @@ postcheck() { return 0 } +pre_split() { + if [ -z "$subpkgname" ]; then + return 0 + fi + # the subpackages should not inherit those form main package + provides="" + install_if="" +} + prepare_subpackages() { local i cd "$startdir" @@ -664,7 +701,7 @@ prepare_subpackages() { msg "Running split function $func..." local dir="$pkgbasedir/${i%:*}" name="${i%:*}" ( subpkgdir="$dir" subpkgname="$name" \ - $0 $func prepare_package \ + $0 pre_split $func prepare_package \ && postcheck "$dir" "$name" ) || return 1 done postcheck "$pkgdir" "$pkgname" || return 1 @@ -804,18 +841,13 @@ EOF echo "replaces_priority = $replaces_priority" >> "$pkginfo" fi - for i in $license; do - echo "license = $i" >> "$pkginfo" - done + echo "license = $license" >> "$pkginfo" 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 @@ -845,7 +877,7 @@ EOF echo $metafiles | tr ' ' '\n' > "$controldir"/.metafiles } -prepare_tracedeps() { +prepare_trace_rpaths() { local dir=${subpkgdir:-$pkgdir} local etype= soname= file= sover= [ "$arch" = "noarch" ] && return 0 @@ -863,6 +895,34 @@ prepare_tracedeps() { fi } +# search for broken symlinks so we later can pull in proper depends +prepare_symlinks() { + local dir="${subpkgdir:-$pkgdir}" + options_has "!tracedeps" && return 0 + cd "$dir" || return 1 + find -type l | while read symlink; do + if ! [ -e "$symlink" ]; then + echo "$symlink $(readlink $symlink)" \ + >> "$controldir"/.symlinks + fi + done +} + +prepare_pkgconfig_provides() { + local dir="${subpkgdir:-$pkgdir}" + options_has "!tracedeps" && return 0 + cd "$dir" || return 1 + for i in usr/lib/pkgconfig/*.pc; do + if ! [ -e "$i" ]; then + continue + fi + local f=${i##*/} + local v=$(PKG_CONFIG_PATH="$dir"/usr/lib/pkgconfig pkg-config \ + --modversion ${f%.pc}) + echo "${f%.pc}=${v:-0}" >> "$controldir"/.provides-pc + done +} + # check if dir has arch specific binaries dir_has_arch_binaries() { local dir="$1" @@ -897,7 +957,11 @@ archcheck() { prepare_package() { msg "Preparing ${subpkgname:+sub}package ${subpkgname:-$pkgname}..." stripbin - prepare_metafiles && prepare_tracedeps || return 1 + prepare_metafiles \ + && prepare_trace_rpaths \ + && prepare_symlinks \ + && prepare_pkgconfig_provides \ + || return 1 archcheck } @@ -930,10 +994,15 @@ find_so_files() { return 0 } -subpkg_provides() { +subpkg_provides_so() { grep -q -w "^$1" "$pkgbasedir"/.control.*/.provides-so 2>/dev/null } +subpkg_provides_pc() { + grep -q -w "^${1%%[<>=]*}" "$pkgbasedir"/.control.*/.provides-pc \ + 2>/dev/null +} + trace_apk_deps() { local name="$1" local dir="$2" @@ -942,21 +1011,22 @@ trace_apk_deps() { # 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 (found /usr/lib/pkgconfig)" autodeps="$autodeps pkgconfig" fi # special case for libpthread: we need depend on libgcc - if [ -f "$dir"/.needs-so ] && grep -q -w '^libpthread.so.*' "$dir"/.needs-so \ + if [ "$CLIBC" = "uclibc" ] && [ -f "$dir"/.needs-so ] \ + && grep -q -w '^libpthread.so.*' "$dir"/.needs-so \ && ! grep -q -w "^depend = libgcc" "$dir"/.PKGINFO; then autodeps="$autodeps libgcc" msg " added libgcc (due to libpthread)" fi + [ -f "$dir"/.needs-so ] && for i in $(cat "$dir"/.needs-so); do # first check if its provided by same apkbuild grep -q -w "^$i" "$dir"/.provides-so 2>/dev/null && continue - if subpkg_provides "$i" || cross_compiling \ + if subpkg_provides_so "$i" || cross_compiling \ || $APK info --quiet --installed "so:$i"; then autodeps="$autodeps so:$i" else @@ -979,11 +1049,39 @@ trace_apk_deps() { autodeps="$autodeps $found" done + # symlink targets + for i in $(sort -u "$dir"/.symlinks-needs 2>/dev/null); do + autodeps="$autodeps $i" + done + + # pkg-config depends + for i in $(sort -u "$dir"/.needs-pc 2>/dev/null); do + if subpkg_provides_pc "$i" || cross_compiling \ + || $APK info --quiet --installed "pc:$i"; then + local provider=$(apk search --quiet "pc:$i") + if list_has "$provider" $depends_dev; then + warning "$provider should be removed from depends_dev" + fi + autodeps="$autodeps pc:$i" + else + warning "Could not find any provider for pc:$i" + local pcfile=/usr/lib/pkgconfig/"${i%%[<>=]*}".pc + if [ -e "$pcfile" ]; then + local owner=$($APK info --quiet --who-owns $pcfile) + warning "${owner:-package providing $pcfile} needs to be rebuilt" + fi + fi + done + echo "# automatically detected:" >> "$dir"/.PKGINFO if [ -f "$dir"/.provides-so ]; then sed 's/^\(.*\) \([0-9].*\)/provides = so:\1=\2/' "$dir"/.provides-so \ >> "$dir"/.PKGINFO fi + if [ -f "$dir"/.provides-pc ]; then + sed 's/^/provides = pc:/' "$dir"/.provides-pc | sort -u \ + >> "$dir"/.PKGINFO + fi [ -z "$autodeps" ] && return 0 for i in $autodeps; do echo "depend = $i" @@ -1017,6 +1115,10 @@ scan_shared_objects() { local name="$1" controldir="$2" datadir="$3" local opt= i= + if [ "$arch" = "noarch" ]; then + return 0 + fi + # allow spaces in paths IFS=: set -- $(find_scanelf_paths "$datadir") @@ -1087,6 +1189,66 @@ scan_shared_objects() { done > "$controldir"/.needs-so } +# normalize a path string +normalize_path() { + local oifs="$IFS" pathstr= i= + IFS='/' + set -- $1 + for i; do + case "$i" in + "."|"") continue;; + "..") pathstr="${pathstr%%/${pathstr##*/}}";; + *) pathstr="${pathstr}/$i";; + esac + done + echo "$pathstr" +} + +# find which package provides file that symlink points to +scan_symlink_targets() { + local name="$1" dir="$2" datadir="$3" + local symfile= targetpath= + cd "$datadir" + for symfile in "$pkgbasedir"/.control.*/.symlinks; do + local d="${symfile%/.symlinks}" + if ! [ -e "$symfile" ] || [ "$d" = "$dir" ]; then + continue + fi + + while read symlink target; do + if [ "${target#/}" = "$target" ]; then + target="${symlink%/*}/$target" + fi + targetpath="$datadir"/$(normalize_path "$target") + if [ -e "$targetpath" ] || [ -L "$targetpath" ]; then + echo "$name=$pkgver-r$pkgrel" \ + >> "$d"/.symlinks-needs + fi + done < "$symfile" + done +} + +#find pkg-config dependencies +scan_pkgconfig_depends() { + local provides_pc="$1" controldir= name= datadir= + [ -e "$provides_pc" ] || return 0 + controldir="${provides_pc%/*}" + name="$(pkginfo_val pkgname "$controldir"/.PKGINFO)" + datadir="$pkgbasedir"/$name + for i in $(sort -u "$provides_pc"); do + PKG_CONFIG_PATH="$datadir"/usr/lib/pkgconfig pkg-config \ + --print-requires \ + --print-requires-private ${i%=*} \ + | sed -E 's/\s*([<>=]+)\s*/\1/' \ + | while read pc; do + # only add files that are not self provided + if ! grep -q -w "^${pc%%[<>=]*}" "$provides_pc"; then + echo "$pc" >> "$controldir"/.needs-pc + fi + done + done +} + # read size in bytes from stdin and show as human readable human_size() { awk '{ split("B KB MB GB TB PB", type) @@ -1099,15 +1261,20 @@ create_apks() { local file= dir= name= ver= apk= datadir= size= getpkgver || return 1 mkdir -p "$PKGDEST" - if [ "$arch" != "noarch" ] && ! options_has "!tracedeps"; then + if ! 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" + scan_symlink_targets "$name" "$dir" "$datadir" + done + for file in "$pkgbasedir"/.control.*/.provides-pc; do + scan_pkgconfig_depends "$file" done fi + for file in "$pkgbasedir"/.control.*/.PKGINFO; do dir="${file%/.PKGINFO}" name=$(pkginfo_val pkgname $file) @@ -1128,7 +1295,7 @@ create_apks() { touch .dummy set -- .dummy fi - tar -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz + tar --xattrs -c "$@" | abuild-tar --hash | gzip -9 >"$dir"/data.tar.gz msg "Create checksum..." # append the hash for data.tar.gz @@ -1224,6 +1391,7 @@ default_doc() { depends="$depends_doc" pkgdesc="$pkgdesc (documentation)" arch=${arch_doc:-"noarch"} + install_if="docs $pkgname=$pkgver-r$pkgrel" local i for i in doc man info html sgml licenses gtk-doc ri help; do @@ -1233,6 +1401,11 @@ default_doc() { fi done + # compress man pages + find "$subpkgdir"/usr/share/man/*[1-9] \ + -type f \! -name \*.gz \! -name \*.bz2 2>/dev/null | + xargs -r gzip -9 + rm -f "$subpkgdir/usr/share/info/dir" # remove if empty, ignore error (not empty) @@ -1273,14 +1446,12 @@ dbg() { # predefined splitfunc dev default_dev() { local i= j= - depends="$pkgname=$pkgver-r$pkgrel $depends_dev" + depends="$depends_dev" pkgdesc="$pkgdesc (development files)" - for i in $origsubpackages; do - [ "${i%:*}" = "$subpkgname" ] || depends="$depends ${i%:*}=$pkgver-r$pkgrel" - done - cd "$pkgdir" || return 0 + local libdirs=usr/ + [ -d lib/ ] && libdirs="lib/ $libdirs" 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]*\ @@ -1288,7 +1459,7 @@ default_dev() { usr/lib/qt*/mkspecs \ usr/lib/cmake \ $(find . -name include -type d) \ - $(find lib/ usr/ -name '*.[acho]' \ + $(find $libdirs -name '*.[acho]' \ -o -name '*.prl' 2>/dev/null); do if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then d="$subpkgdir/${i%/*}" # dirname $i @@ -1443,11 +1614,12 @@ abuildindex() { # 1) origin of package # 2) all dependencies # the output is i in a format easy parseable for awk -depparse_aports() { +parse_aports_makedepends() { # lets run this in a subshell since we source all APKBUILD here ( aportsdir=$(realpath ${APKBUILD%/APKBUILD}/..) for i in $aportsdir/*/APKBUILD; do + # no forks in this loop or it will be painfully slow! pkgname= subpackages= depends= @@ -1477,14 +1649,14 @@ depparse_aports() { ) } -deptrace() { +trace_makedepends() { local deps= i= # strip versions from deps for i in "$@"; do deps="$deps ${i%%[<>=]*}" done [ -z "$deps" ] && return 0 - ( depparse_aports + ( parse_aports_makedepends if [ -z "$upgrade" ]; then # list installed pkgs and prefix with 'i ' $APK info --quiet | sort | sed 's/^/i /' @@ -1515,7 +1687,7 @@ deptrace() { # build and install dependencies builddeps() { - local pkg= i= missing= conflicts= + local pkg= i= missing= local hostdeps= builddeps= installed_hostdeps= installed_builddeps= [ -n "$nodeps" ] && return 0 msg "Analyzing dependencies..." @@ -1545,27 +1717,20 @@ builddeps() { # find which deps are missing for i in $builddeps; do - if [ "${i#\!}" != "$i" ]; then - $APK info --quiet --installed "${i#\!}" \ - && conflicts="$conflicts ${i#\!}" + if [ "${i#\!}" != "$i" ] && $APK info --quiet --installed "${i#\!}"; then + error "Conflicting package installed: ${i#\!}" elif ! deplist_has $i $installed_builddeps || [ -n "$upgrade" ]; then missing="$missing $i" fi done for i in $hostdeps; do - if [ "${i#\!}" != "$i" ]; then - $APK info --quiet --installed --root "$CBUILDROOT" "${i#\!}" \ - && conflicts="$conflicts ${i#\!}" + if [ "${i#\!}" != "$i" ] && $APK info --quiet --installed --root "$CBUILDROOT" "${i#\!}"; then + error "Conflicting package installed: ${i#\!}" elif ! deplist_has $i $installed_hostdeps || [ -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 @@ -1577,7 +1742,6 @@ builddeps() { if [ -n "$install_deps" ] && [ -z "$recursive" ]; then # make a --simulate run first to detect missing deps # apk-tools --virtual is no goot at reporting those. - msg "Installing packages on builder: $builddeps" $SUDO_APK add --repository "$abuildrepo" $apk_opt_wait \ --simulate --quiet $builddeps || return 1 $SUDO_APK add --repository "$abuildrepo" $apk_opt_wait \ @@ -1605,7 +1769,7 @@ builddeps() { fi done - for i in $(deptrace $missing); do + for i in $(trace_makedepends $missing); do # i = pkg:dir local dir=${i#*:} local pkg=${i%:*} @@ -1671,7 +1835,11 @@ stripbin() { msg "Stripping binaries" scanelf --recursive --nobanner --etype "ET_DYN,ET_EXEC" . \ | sed -e 's:^ET_DYN ::' -e 's:^ET_EXEC ::' \ - | xargs -r ${CROSS_COMPILE}strip + | while read filename; do + XATTR=$(getfattr --match="*" --dump "${filename}") + ${CROSS_COMPILE}strip "${filename}" + [ -n "$XATTR" ] && (echo "$XATTR" | setfattr --restore=-) + done } # simply list target apks @@ -1794,6 +1962,7 @@ undeps (){ # compat installdeps() { deps; } uninstalldeps() { undeps; } +index() { update_abuildrepo_index; } all() { if ! [ -n "$force" ]; then @@ -1869,49 +2038,52 @@ snapshot() { usage() { echo "$program $program_version" - echo "usage: $program [options] [-i PKG] [-P REPODEST] [-p PKGDEST]" - echo " [-s SRCDEST] [cmd] ..." - echo " $program [-c] -n PKGNAME[-PKGVER]" - echo "Options:" - echo " -a Print CARCH and exit" - 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 successful 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/<repo>/\$CARCH, 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 " verify Verify checksums" - echo " unpack Unpack sources to \$srcdir" - echo " prepare Apply patches" - echo " build Compile and install package into \$pkgdir" - echo " listpkg List target packages" - echo " package Create package in \$PKGDEST" - echo " rootpkg Run 'package', the split functions and create apks 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 " deps Install packages listed in makedepends and depends" - echo " undeps Uninstall packages listed in makedepends and depends" - echo " snapshot Create a \$giturl or \$svnurl snapshot and upload to \$disturl" - echo "" + cat << EOF +usage: $program [options] [-i PKG] [-P REPODEST] [-p PKGDEST] + [-s SRCDEST] [cmd] ... + $program [-c] -n PKGNAME[-PKGVER] +Options: + -A Print CARCH and exit + -c Enable colored output + -d Disable dependency checking + -f Force specified cmd, even if they are already done + -F Force run as root + -h Show this help + -i Install PKG after successful build + -k Keep built packages, even if APKBUILD or sources are newer + -m Disable colors (monochrome) + -p Set package destination directory + -P Set PKGDEST to REPODEST/<repo>/\$CARCH, where repo is the parents dir name + -q Quiet + -r Install missing dependencies from system repository (using sudo) + -R Recursively build and install missing dependencies (using sudo) + -s Set source package destination directory + -u Recursively build and upgrade all dependencies (using sudo) + +Commands: + build Compile and install package into \$pkgdir + checksum Generate checksum to be included in APKBUILD + clean Remove temp build and install dirs + cleancache Remove downloaded files from \$SRCDEST + cleanoldpkg Remove binary packages except current version + cleanpkg Remove already built binary and source package + deps Install packages listed in makedepends and depends + fetch Fetch sources to \$SRCDEST and verify checksums + index Regenerate the APKINDEX for abuildrepo + listpkg List target packages + package Create package in \$PKGDEST + prepare Apply patches + rootpkg Run 'package', the split functions and create apks as fakeroot + sanitycheck Basic sanity check of APKBUILD + snapshot Create a \$giturl or \$svnurl snapshot and upload to \$disturl + sourcecheck Check if remote source package exists upstream + srcpkg Make a source package + undeps Uninstall packages listed in makedepends and depends + unpack Unpack sources to \$srcdir + up2date Compare target and sources dates + verify Verify checksums + +EOF exit 0 } @@ -1984,6 +2156,7 @@ fi # if we want build debug package if [ -n "$DEBUG" ] || subpackage_types_has "dbg"; then CFLAGS="$CFLAGS -g" + CXXFLAGS="$CXXFLAGS -g" options="$options !strip" fi |