diff --git a/abuild.in b/abuild.in index 2780d2e..0bf9d47 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 @@ -858,11 +858,15 @@ find_so_files() { return 0 } +subpkg_provides() { + grep -q -w "^$1" "$pkgbasedir"/.control.*/.provides-so 2>/dev/null +} + 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..." + local i= found= autodeps= deppkgs= missing= + 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 @@ -877,18 +881,11 @@ trace_apk_deps() { msg " added libgcc (due to libpthread)" fi [ -f "$dir"/.needs-so ] && for i in $(cat "$dir"/.needs-so); 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 - if [ -n "$found" ]; then - if ! list_has "$found" $self_provided; then - self_provided="$self_provided $found" - fi + # first check if its provided by same apkbuild + grep -q -w "^$i" "$dir"/.provides-so 2>/dev/null && continue + + if subpkg_provides "$i" || $APK info -q -e "so:$i"; then + autodeps="$autodeps so:$i" else missing="$missing $i" fi @@ -896,41 +893,131 @@ trace_apk_deps() { # find all packages that holds the so files if [ -f "$dir"/.rpaths ]; then - so_files=$(find_so_files "$dir"/.rpaths $missing) || return 1 + local so_files=$(find_so_files "$dir"/.rpaths $missing) \ + || return 1 deppkgs=$($APK info -q -W $so_files) || return 1 fi - for found in $self_provided $deppkgs; do + for found in $deppkgs; do if grep -w "^depend = ${found}$" "$dir"/.PKGINFO >/dev/null ; then warning "You can remove '$found' from depends" continue fi - if [ "$found" != "$name" ] && ! list_has "$found" $autodeps; then - autodeps="$autodeps $found" - msg " added $found" - fi + autodeps="$autodeps $found" 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 + # display all depends + sed -n '/^depend =/s/depend = /\t/p' "$dir"/.PKGINFO >&2 +} + +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]*) + if options_has "sover-namecheck"; then + continue + fi + 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 +1028,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 +1039,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() {