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.
This commit is contained in:
Yann E. MORIN" 2010-03-29 00:15:32 +02:00
parent ec4181e4d2
commit d8d2459ca4

View File

@ -184,6 +184,12 @@ do_add_lib() {
local dir local dir
local mode 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 for dir in lib usr/lib; do
${CT_PRINTF} " trying in '%s'" "${dir}" ${CT_PRINTF} " trying in '%s'" "${dir}"
libfile="${CT_SYSROOT_DIR}/${dir}/${libname}" libfile="${CT_SYSROOT_DIR}/${dir}/${libname}"
@ -200,12 +206,36 @@ do_add_lib() {
esac esac
${CT_PRINTF} " installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}" ${CT_PRINTF} " installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}"
"${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}" "${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}"
do_resolve_deps "${dir}/${true_libname}"
return 0 return 0
fi fi
done done
return 1 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 # We'll work in the copied rootfs
cd "${CT_ROOT_DST_DIR}" cd "${CT_ROOT_DST_DIR}"
@ -223,12 +253,11 @@ CT_LIB_LIST=$(printf "${CT_LIB_LIST}:${lib_list}\n" \
|"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \ |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
) )
if [ -n "${CT_LIB_LIST}" ]; then if [ -n "${CT_LIB_LIST}" ]; then
${CT_PRINTF} "Installing forced libraries...\n"
for name in ${CT_LIB_LIST}; do for name in ${CT_LIB_LIST}; do
[ -z "${name}" ] && continue [ -z "${name}" ] && continue
found=0 found=0
for libname in "lib${name}.so" "${name}.so" "${name}"; do 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 if do_add_lib "${libname}"; then
found=1 found=1
break break
@ -241,35 +270,28 @@ if [ -n "${CT_LIB_LIST}" ]; then
done done
fi fi
# Parse the working copy for executables and libraries # Create a temporary place where to store... temp files.
still_needed=1 rand="$( dd if=/dev/urandom bs=1024 count=1 2>/dev/null \
while [ ${still_needed} -eq 1 ]; do |md5sum \
${CT_PRINTF} "Looping...\n" |awk '{ print $1; }'
still_needed=0 )"
for f in $(find . -type f -exec file {} \; \ CT_TMP_DIR="${TMPDIR:-/tmp}/populate-${rand}-${$}"
|"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),' \ ( umask 0077; mkdir "${CT_TMP_DIR}" ) || { printf "Could not create temporary directory\n"; exit 1; }
|cut -d ":" -f 1 \ trap "rm -rf ${CT_TMP_DIR}" EXIT
); do
${CT_PRINTF} "Scanning '%s'\n" "${f}" # List all ELF (executables|shared objects)...
for libname in $("${CT_READELF}" -d "${f}" \ find . -type f -exec file {} \; \
|"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:' \ |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),' \
|"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;' \ |cut -d ":" -f 1 \
); do >"${CT_TMP_DIR}/files.list"
${CT_PRINTF} " searching for '%s'\n" "${libname}"
if [ -e "lib/${libname}" \ # ... and use that list to find missing dependencies
-o -e "usr/lib/${libname}" ]; then while read file; do
${CT_PRINTF} " already present\n" do_resolve_deps "${file}"
continue done <"${CT_TMP_DIR}/files.list"
fi
if do_add_lib "${libname}"; then rm -rf "${CT_TMP_DIR}"
still_needed=1 trap - EXIT
else
printf "$myname: library '${libname}' not found!\n"
[ "${CT_FORCE}" = "y" ] || exit 1
fi
done
done
done
# OK, we're done. Back off. # OK, we're done. Back off.
cd - >/dev/null cd - >/dev/null