scripts/populate: optimise search loop
author"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Mon Mar 29 00:15:32 2010 +0200 (2010-03-29)
changeset 1864758d5137fe87
parent 1863 11cc7a5102fa
child 1865 6a0b74b87dbd
scripts/populate: optimise search loop

Curently, populate will iterate over all ELF (shared objects|executables)
to look for missing NEEDED DSOs, adding to the list at every iterations
of the search loop.

Instead of looking again at previously handled ELF files, recursively
resolve every ELf files.

Also, in case there are a whole lot of files (more than the shell can
accept as arguments list, or creating a command line longer than the
shell can cope with), use a temporary file with the list of files
to search for missing dependencies.
scripts/populate.in
     1.1 --- a/scripts/populate.in	Sun Mar 28 23:01:19 2010 +0200
     1.2 +++ b/scripts/populate.in	Mon Mar 29 00:15:32 2010 +0200
     1.3 @@ -185,6 +185,12 @@
     1.4      local mode
     1.5  
     1.6      for dir in lib usr/lib; do
     1.7 +        if [ -e "${dir}/${libname}" ]; then
     1.8 +            ${CT_PRINTF} "    already present\n"
     1.9 +            return 0
    1.10 +        fi
    1.11 +    done
    1.12 +    for dir in lib usr/lib; do
    1.13          ${CT_PRINTF} "    trying in '%s'" "${dir}"
    1.14          libfile="${CT_SYSROOT_DIR}/${dir}/${libname}"
    1.15          ${CT_PRINTF} ": '%s'\n" "${libfile}"
    1.16 @@ -200,12 +206,36 @@
    1.17              esac
    1.18              ${CT_PRINTF} "      installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}"
    1.19              "${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}"
    1.20 +            do_resolve_deps "${dir}/${true_libname}"
    1.21              return 0
    1.22          fi
    1.23      done
    1.24      return 1
    1.25  }
    1.26  
    1.27 +# A function to resolve all NEEDED entries for the given file, relative
    1.28 +# to the working directory (eg. dst_dir)
    1.29 +# Usage: do_resolve_deps some/where/some/file
    1.30 +# Returns: 0, meaning all dependencies were found
    1.31 +# If not all dependencies could be found, exists with error code 1
    1.32 +# (unless forced)
    1.33 +do_resolve_deps() {
    1.34 +    local file="${1}"
    1.35 +    local libname
    1.36 +    
    1.37 +    for libname in $("${CT_READELF}" -d "${file}"                           \
    1.38 +                     |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:'  \
    1.39 +                     |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'                 \
    1.40 +                    ); do
    1.41 +        [ -n "${libname}" ] || continue
    1.42 +        ${CT_PRINTF} "Searching for '%s' needed by '%s'\n" "${libname}" "${file}"
    1.43 +        if ! do_add_lib "${libname}"; then
    1.44 +            printf "$myname: library '${libname}' not found!\n"
    1.45 +            [ "${CT_FORCE}" = "y" ] || exit 1
    1.46 +        fi
    1.47 +    done
    1.48 +}
    1.49 +
    1.50  # We'll work in the copied rootfs
    1.51  cd "${CT_ROOT_DST_DIR}"
    1.52  
    1.53 @@ -223,12 +253,11 @@
    1.54                |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
    1.55               )
    1.56  if [ -n "${CT_LIB_LIST}" ]; then
    1.57 -    ${CT_PRINTF} "Installing forced libraries...\n"
    1.58      for name in ${CT_LIB_LIST}; do
    1.59          [ -z "${name}" ] && continue
    1.60          found=0
    1.61          for libname in "lib${name}.so" "${name}.so" "${name}"; do
    1.62 -            ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
    1.63 +            ${CT_PRINTF} "Searching for forced library '%s'\n" "${libname}"
    1.64              if do_add_lib "${libname}"; then
    1.65                  found=1
    1.66                  break
    1.67 @@ -241,35 +270,28 @@
    1.68      done
    1.69  fi
    1.70  
    1.71 -# Parse the working copy for executables and libraries
    1.72 -still_needed=1
    1.73 -while [ ${still_needed} -eq 1 ]; do
    1.74 -    ${CT_PRINTF} "Looping...\n"
    1.75 -    still_needed=0
    1.76 -    for f in $(find . -type f -exec file {} \;                                              \
    1.77 -               |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),'   \
    1.78 -               |cut -d ":" -f 1                                                             \
    1.79 -              ); do
    1.80 -        ${CT_PRINTF} "Scanning '%s'\n" "${f}"
    1.81 -        for libname in $("${CT_READELF}" -d "${f}"                              \
    1.82 -                         |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:'  \
    1.83 -                         |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'                 \
    1.84 -                        ); do
    1.85 -            ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
    1.86 -            if [    -e "lib/${libname}"     \
    1.87 -                 -o -e "usr/lib/${libname}" ]; then
    1.88 -                ${CT_PRINTF} "    already present\n"
    1.89 -                continue
    1.90 -            fi
    1.91 -            if do_add_lib "${libname}"; then
    1.92 -                still_needed=1
    1.93 -            else
    1.94 -                printf "$myname: library '${libname}' not found!\n"
    1.95 -                [ "${CT_FORCE}" = "y" ] || exit 1
    1.96 -            fi
    1.97 -        done
    1.98 -    done
    1.99 -done
   1.100 +# Create a temporary place where to store... temp files.
   1.101 +rand="$( dd if=/dev/urandom bs=1024 count=1 2>/dev/null \
   1.102 +         |md5sum                                        \
   1.103 +         |awk '{ print $1; }'
   1.104 +       )"
   1.105 +CT_TMP_DIR="${TMPDIR:-/tmp}/populate-${rand}-${$}"
   1.106 +( umask 0077; mkdir "${CT_TMP_DIR}" ) || { printf "Could not create temporary directory\n"; exit 1; }
   1.107 +trap "rm -rf ${CT_TMP_DIR}" EXIT
   1.108 +
   1.109 +# List all ELF (executables|shared objects)...
   1.110 +find . -type f -exec file {} \;                                             \
   1.111 +|"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),'  \
   1.112 +|cut -d ":" -f 1                                                            \
   1.113 +>"${CT_TMP_DIR}/files.list"
   1.114 +
   1.115 +# ... and use that list to find missing dependencies
   1.116 +while read file; do
   1.117 +    do_resolve_deps "${file}"
   1.118 +done <"${CT_TMP_DIR}/files.list"
   1.119 +
   1.120 +rm -rf "${CT_TMP_DIR}"
   1.121 +trap - EXIT
   1.122  
   1.123  # OK, we're done. Back off.
   1.124  cd - >/dev/null