scripts/populate.in
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Fri Aug 06 23:45:18 2010 +0200 (2010-08-06)
branch1.6
changeset 2065 c1449228cbb5
parent 1678 ac247da318a1
permissions -rw-r--r--
1.6: close branch
     1 #!@@CT_bash@@
     2 # This script will populate the root directory with libs from the sysroot.
     3 # (C) 2007 Yann E. MORIN
     4 # Licensed under the GPL v2
     5 set -e
     6 
     7 # Detect where the toolchain is:
     8 CT_PREFIX_DIR="$(cd "$(dirname "$0")/.."; pwd)"
     9 CT_BIN_DIR="${CT_PREFIX_DIR}/bin"
    10 CT_READELF="${CT_BIN_DIR}/@@CT_TARGET@@-readelf"
    11 CT_LIB_DIR="${CT_PREFIX_DIR}/lib"
    12 CT_SYSROOT_DIR="$(cd "${CT_BIN_DIR}/../@@CT_TARGET@@/sys-root"; pwd)"
    13 
    14 myname=$(basename "$0")
    15 
    16 # Use the tools discovered by crosstool-NG's ./configure:
    17 install="@@CT_install@@"
    18 grep="@@CT_grep@@"
    19 sed="@@CT_sed@@"
    20 
    21 doHelp() {
    22     cat <<_EOF_
    23 NAME
    24     $myname - populate the target root file system
    25 
    26 SYNOPSIS
    27     $myname OPTIONS -s source_root -d destination_root
    28 
    29 DESCRIPTION
    30     $myname will 'populate' your target root file system ('src_dir') with
    31     libraries from the toolchain (eg. libc.so...), storing the result into
    32     'dst_dir'.
    33 
    34 OPTIONS
    35     -s src_dir
    36         use 'src_dir' as the un-populated (source) root directory
    37 
    38     -d dst_dir
    39         use 'dst_dir' as the place to put the populated root directory
    40 
    41     -l name1[:name2[...]]
    42         Always add the specified shared library/ies name1, name2... from the
    43         toolchain (in the sys-root). Actual library names are searched as
    44         follows (where 'name' is replaced with the given name) in the
    45         sys-root directory:
    46           - libname.so
    47           - name.so
    48           - name
    49         If the file is found, then the SONAME of the library is used, and the
    50         library is copied with that name. If the library was not found, this
    51         yields an error (unless -f was given).
    52 
    53     -L file
    54         Read 'file' for a list of shared libraries to always add from the
    55         toolchain. The file should contain one library name per line; text
    56         after a # is ignored until the end of the line; spaces are ignored;
    57         empty lines are ignored. Libraries are searched for as with -l.
    58 
    59     -f  force execution: if destination directory already exists, it will be
    60         removed first; if a specified library (above) was not found, continue.
    61 
    62     -v  Be verbose. By default, populate is absolutely silent.
    63 
    64 _EOF_
    65 }
    66 
    67 CT_ROOT_SRC_DIR=
    68 CT_ROOT_DST_DIR=
    69 CT_LIB_LIST=
    70 CT_LIB_FILE=
    71 CT_FORCE=no
    72 CT_PRINTF=:
    73 OPTIND=1
    74 while getopts ":s:d:l:L:fvh" CT_OPT; do
    75     case "${CT_OPT}" in
    76         s)  CT_ROOT_SRC_DIR="${OPTARG}";;
    77         d)  CT_ROOT_DST_DIR="${OPTARG}";;
    78         l)  CT_LIB_LIST="${CT_LIB_LIST}:${OPTARG}";;
    79         L)  CT_LIB_FILE="${OPTARG}";;
    80         f)  CT_FORCE=y;;
    81         v)  CT_PRINTF=printf;;
    82         h)  doHelp
    83             exit 0
    84             ;;
    85         :)  echo "$myname: '-${OPTARG}' takes exactly one argument."
    86             exit 1
    87             ;;
    88         ?)  echo "$myname: unknown option '-${OPTARG}'."
    89             exit 1
    90             ;;
    91     esac
    92 done
    93 
    94 # Sanity checks
    95 if [ -z "${CT_ROOT_SRC_DIR}" -o -z "${CT_ROOT_DST_DIR}" ]; then
    96     doHelp
    97     exit 1
    98 fi
    99 if [ ! -d "${CT_ROOT_SRC_DIR}" ]; then
   100     echo "$myname: '${CT_ROOT_SRC_DIR}': no such file or directory"
   101     exit 1
   102 fi
   103 if [ -d "${CT_ROOT_DST_DIR}" -a "${CT_FORCE}" != "y" ]; then
   104     echo "$myname: '${CT_ROOT_DST_DIR}': already exists"
   105     exit 1
   106 fi
   107 src_inode=$(stat -c '%i' "${CT_ROOT_SRC_DIR}/.")
   108 dst_inode=$(stat -c '%i' "${CT_ROOT_DST_DIR}/." 2>/dev/null || true)
   109 if [ "${src_inode}" -eq "$((dst_inode+0))" ]; then
   110     echo "$myname: source and destination are the same!"
   111     exit 1
   112 fi
   113 
   114 # Check existence of the forced libraries file
   115 if [ -n "${CT_LIB_FILE}" -a ! \( -f "${CT_LIB_FILE}" -a -r "${CT_LIB_FILE}" \) ]; then
   116     echo "$myname: forced libraries file '${CT_LIB_FILE}' not found!"
   117     exit 1
   118 fi
   119 
   120 # Get rid of potentially older destination directory
   121 rm -rf "${CT_ROOT_DST_DIR}"
   122 
   123 # Create the working copy
   124 mkdir -p "${CT_ROOT_DST_DIR}"
   125 
   126 # Make all path absolute
   127 CT_ROOT_SRC_DIR=$(cd "${CT_ROOT_SRC_DIR}"; pwd)
   128 CT_ROOT_DST_DIR=$(cd "${CT_ROOT_DST_DIR}"; pwd)
   129 
   130 # Populate the destination directory with files from the source directory
   131 pushd "${CT_ROOT_SRC_DIR}" >/dev/null
   132 cp -a . "${CT_ROOT_DST_DIR}"
   133 popd >/dev/null
   134 
   135 # A function do search for a library
   136 # Usage: do_add_lib libname
   137 # returns: 0 if library was found and added, !0 otherwise
   138 do_add_lib() {
   139     local libname="$1"
   140     local true_libname
   141     local dir
   142     local mode
   143 
   144     for dir in lib usr/lib; do
   145         ${CT_PRINTF} "    trying in '%s'" "${dir}"
   146         libfile="${CT_SYSROOT_DIR}/${dir}/${libname}"
   147         ${CT_PRINTF} ": '%s'\n" "${libfile}"
   148         if [ -e "${libfile}" ]; then
   149             mkdir -p "${dir}"
   150             true_libname=$("${CT_READELF}" -d "${libfile}"          \
   151                            |"${grep}" "Library soname:"             \
   152                            |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'   \
   153                           )
   154             case "${libfile}" in
   155                 */ld*)  mode=0755;;
   156                 *)      mode=0644;;
   157             esac
   158             ${CT_PRINTF} "      installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}"
   159             "${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}"
   160             return 0
   161             break
   162         fi
   163     done
   164     return 1
   165 }
   166 
   167 # We'll work in the copied rootfs
   168 pushd "${CT_ROOT_DST_DIR}" >/dev/null
   169 
   170 # First of, copy the forced libraries into the working copy
   171 lib_list=
   172 if [ -n "${CT_LIB_FILE}" ]; then
   173     lib_list=$("${sed}" -r -e ':loop; s/#.*//;'         \
   174                            -e 's/[[:space:]]+//g;'      \
   175                            -e 's/([^:])$/\1:/;'         \
   176                            -e '/$/N; s/\n//; tloop;'    \
   177                         "${CT_LIB_FILE}"
   178               )
   179 fi
   180 CT_LIB_LIST=$(echo "${CT_LIB_LIST}:${lib_list}"             \
   181               |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
   182              )
   183 if [ -n "${CT_LIB_LIST}" ]; then
   184     ${CT_PRINTF} "Installing forced libraries...\n"
   185     for name in ${CT_LIB_LIST}; do
   186         [ -z "${name}" ] && continue
   187         found=0
   188         for libname in "lib${name}.so" "${name}.so" "${name}"; do
   189             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   190             if do_add_lib "${libname}"; then
   191                 found=1
   192                 break
   193             fi
   194         done
   195         if [ ${found} -eq 0 ]; then
   196             echo "$myname: library '${libname}' not found!"
   197             [ "${CT_FORCE}" = y ] || exit 1
   198         fi
   199     done
   200 fi
   201 
   202 # Parse the working copy for executables and libraries
   203 still_needed=1
   204 while [ ${still_needed} -eq 1 ]; do
   205     ${CT_PRINTF} "Looping...\n"
   206     still_needed=0
   207     for f in $(find . -type f -exec file {} \;                                              \
   208                |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),'   \
   209                |cut -d ":" -f 1                                                             \
   210               ); do
   211         ${CT_PRINTF} "Scanning '%s'\n" "${f}"
   212         for libname in $("${CT_READELF}" -d "${f}"                              \
   213                          |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:'  \
   214                          |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'                 \
   215                         ); do
   216             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   217             if [    -e "lib/${libname}"     \
   218                  -o -e "usr/lib/${libname}" ]; then
   219                 ${CT_PRINTF} "    already present\n"
   220                 continue
   221             fi
   222             if do_add_lib "${libname}"; then
   223                 still_needed=1
   224             else
   225                 echo "$myname: library '${libname}' not found!"
   226             fi
   227         done
   228     done
   229 done
   230 
   231 # OK, we're done. Back off.
   232 popd >/dev/null