# HG changeset patch # User "Yann E. MORIN" # Date 1269814532 -7200 # Node ID 758d5137fe87ab34d0e2289c5620188ab6e69810 # Parent 11cc7a5102fa6e7a825321a38fb420ca4aa55b7c 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. diff -r 11cc7a5102fa -r 758d5137fe87 scripts/populate.in --- a/scripts/populate.in Sun Mar 28 23:01:19 2010 +0200 +++ b/scripts/populate.in Mon Mar 29 00:15:32 2010 +0200 @@ -185,6 +185,12 @@ local mode for dir in lib usr/lib; do + if [ -e "${dir}/${libname}" ]; then + ${CT_PRINTF} " already present\n" + return 0 + fi + done + for dir in lib usr/lib; do ${CT_PRINTF} " trying in '%s'" "${dir}" libfile="${CT_SYSROOT_DIR}/${dir}/${libname}" ${CT_PRINTF} ": '%s'\n" "${libfile}" @@ -200,12 +206,36 @@ esac ${CT_PRINTF} " installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}" "${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}" + do_resolve_deps "${dir}/${true_libname}" return 0 fi done return 1 } +# A function to resolve all NEEDED entries for the given file, relative +# to the working directory (eg. dst_dir) +# Usage: do_resolve_deps some/where/some/file +# Returns: 0, meaning all dependencies were found +# If not all dependencies could be found, exists with error code 1 +# (unless forced) +do_resolve_deps() { + local file="${1}" + local libname + + for libname in $("${CT_READELF}" -d "${file}" \ + |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:' \ + |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;' \ + ); do + [ -n "${libname}" ] || continue + ${CT_PRINTF} "Searching for '%s' needed by '%s'\n" "${libname}" "${file}" + if ! do_add_lib "${libname}"; then + printf "$myname: library '${libname}' not found!\n" + [ "${CT_FORCE}" = "y" ] || exit 1 + fi + done +} + # We'll work in the copied rootfs cd "${CT_ROOT_DST_DIR}" @@ -223,12 +253,11 @@ |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \ ) if [ -n "${CT_LIB_LIST}" ]; then - ${CT_PRINTF} "Installing forced libraries...\n" for name in ${CT_LIB_LIST}; do [ -z "${name}" ] && continue found=0 for libname in "lib${name}.so" "${name}.so" "${name}"; do - ${CT_PRINTF} " searching for '%s'\n" "${libname}" + ${CT_PRINTF} "Searching for forced library '%s'\n" "${libname}" if do_add_lib "${libname}"; then found=1 break @@ -241,35 +270,28 @@ done fi -# Parse the working copy for executables and libraries -still_needed=1 -while [ ${still_needed} -eq 1 ]; do - ${CT_PRINTF} "Looping...\n" - still_needed=0 - for f in $(find . -type f -exec file {} \; \ - |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),' \ - |cut -d ":" -f 1 \ - ); do - ${CT_PRINTF} "Scanning '%s'\n" "${f}" - for libname in $("${CT_READELF}" -d "${f}" \ - |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:' \ - |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;' \ - ); do - ${CT_PRINTF} " searching for '%s'\n" "${libname}" - if [ -e "lib/${libname}" \ - -o -e "usr/lib/${libname}" ]; then - ${CT_PRINTF} " already present\n" - continue - fi - if do_add_lib "${libname}"; then - still_needed=1 - else - printf "$myname: library '${libname}' not found!\n" - [ "${CT_FORCE}" = "y" ] || exit 1 - fi - done - done -done +# Create a temporary place where to store... temp files. +rand="$( dd if=/dev/urandom bs=1024 count=1 2>/dev/null \ + |md5sum \ + |awk '{ print $1; }' + )" +CT_TMP_DIR="${TMPDIR:-/tmp}/populate-${rand}-${$}" +( umask 0077; mkdir "${CT_TMP_DIR}" ) || { printf "Could not create temporary directory\n"; exit 1; } +trap "rm -rf ${CT_TMP_DIR}" EXIT + +# List all ELF (executables|shared objects)... +find . -type f -exec file {} \; \ +|"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),' \ +|cut -d ":" -f 1 \ +>"${CT_TMP_DIR}/files.list" + +# ... and use that list to find missing dependencies +while read file; do + do_resolve_deps "${file}" +done <"${CT_TMP_DIR}/files.list" + +rm -rf "${CT_TMP_DIR}" +trap - EXIT # OK, we're done. Back off. cd - >/dev/null