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 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}"
@ -200,12 +206,36 @@ do_add_lib() {
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 @@ CT_LIB_LIST=$(printf "${CT_LIB_LIST}:${lib_list}\n" \
|"${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 @@ if [ -n "${CT_LIB_LIST}" ]; then
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