diff --git a/abuild.in b/abuild.in index 2780d2e..5c6c3dd 100755 --- a/abuild.in +++ b/abuild.in @@ -404,6 +404,9 @@ default_unpack() { for u in $source; do local s="$SRCDEST/${u##*/}" # $(basename $s) case "$s" in + *.tar) + msg "Unpacking $s..." + tar -C "$srcdir" -xf "$s" || return 1;; *.tar.gz|*.tgz) msg "Unpacking $s..." tar -C "$srcdir" -zxf "$s" || return 1;; @@ -772,23 +775,20 @@ EOF prepare_tracedeps() { local dir=${subpkgdir:-$pkgdir} + local etype= soname= file= sover= [ "$arch" = "noarch" ] && return 0 options_has "!tracedeps" && return 0 - # lets tell all the .so files this package provides in .provides-so - find -name '*.so' -o -name '*.so.[0-9]*' | sed 's:.*/::' \ - >"$controldir"/.provides-so # lets tell all the places we should look for .so files - all rpaths - scanelf -q -Rr "$dir" | sed -e 's/[[:space:]].*//' -e 's/:/\n/' \ - | sort | uniq \ + scanelf --quiet --recursive --rpath "$dir" \ + | sed -e 's/[[:space:]].*//' -e 's/:/\n/' | sort -u \ >"$controldir"/.rpaths - # now find the so dependencies - scanelf -Rn "$dir" | tr ' ' ':' | 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 + if grep -q -x '/usr/lib' "$controldir"/.rpaths; then + warning "Redundat /usr/lib in rpath found" + fi + if grep '^/home/' "$controldir"/.rpaths; then + error "Has /home/... in rpath" + return 1 + fi } # check if dir has arch specific binaries @@ -862,7 +862,7 @@ trace_apk_deps() { local name="$1" local dir="$2" local i= j= found= autodeps= deppkgs= missing= so_paths= self_provided= - msg "Tracing dependencies for $name..." + msg "Tracing dependencies..." # add pkgconfig if usr/lib/pkgconfig is found if [ -d "$pkgbasedir"/$name/usr/lib/pkgconfig ] \ && ! grep -q '^depend = pkgconfig' "$dir"/.PKGINFO; then @@ -880,7 +880,7 @@ trace_apk_deps() { found= # first check if its provide by same apkbuild for j in "$dir"/../.control.*/.provides-so; do - grep -w "$i" "$j" >/dev/null || continue + grep -q -w "^$i" "$j" || continue found=${j%/.provides-so} found=${found##*/.control.} break @@ -890,7 +890,11 @@ trace_apk_deps() { self_provided="$self_provided $found" fi else - missing="$missing $i" + if $APK info --quiet --installed "so:$i"; then + autodeps="$autodeps so:$i" + else + missing="$missing $i" + fi fi done @@ -911,26 +915,113 @@ trace_apk_deps() { fi done - [ -z "$autodeps" ] && return 0 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 + [ -z "$autodeps" ] && return 0 for i in $autodeps; do - echo "depend = $i" >> "$dir"/.PKGINFO + echo "depend = $i" + done | sort -u >> "$dir"/.PKGINFO +} + +find_scanelf_paths() { + local datadir="$1" + local paths="$datadir/lib:$datadir/usr/lib" i= rpaths= + if [ -n "$ldpath" ]; then + paths="$paths:$(echo "$ldpath" | sed "s|\(^\|:\)|\1$datadir|g")" + fi + # search in all rpaths + for rpaths in "$pkgbasedir"/.control.*/.rpaths; do + [ -f "$rpaths" ] || continue + while read i; do + local dir="${datadir}${i}" + IFS=: + if [ -d "$dir" ] && ! list_has "$dir" $paths; then + paths="$paths:${dir}" + fi + unset IFS + done < "$rpaths" done + echo "$paths" +} + +scan_shared_objects() { + local name="$1" controldir="$2" datadir="$3" + local opt= + + # 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]*) continue;; + esac + ;; + esac + echo "$soname $sover" + done | sort -u > "$controldir"/.provides-so + + # 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 \ + | while read i; do + # only add files that are not self provided + grep -q -w "^$i" "$controldir"/.provides-so \ + || echo $i + done > "$controldir"/.needs-so } create_apks() { - local file + local file= dir= name= ver= apk= datadir= getpkgver || return 1 mkdir -p "$PKGDEST" + 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 - 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 + dir="${file%/.PKGINFO}" + name=$(pkginfo_val pkgname $file) + ver=$(pkginfo_val pkgver $file) + apk=$name-$ver.apk + datadir="$pkgbasedir"/$name + subpkgname=$name trace_apk_deps "$name" "$dir" || return 1 - msg "Creating $apk..." + msg "Compressing data..." ( cd "$datadir" # data.tar.gz @@ -941,6 +1032,7 @@ create_apks() { 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 @@ -951,10 +1043,12 @@ create_apks() { | 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 - ) + ) done + subpkgname= } clean_abuildrepo() {