scripts/populate.in
author Yann E. MORIN
Wed Jun 17 11:38:04 2009 +0200 (2009-06-17)
changeset 1410 23a8ffdf8574
parent 1352 d7ddcb75e0f7
parent 1400 ee206adb53a7
child 1678 ac247da318a1
permissions -rw-r--r--
[gcc] Merge the gcc-4.4 suport to the default branch, from 1407:83083566fdd0
     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 form the source directory
   131 pushd "${CT_ROOT_SRC_DIR}" >/dev/null
   132 tar cf - . |tar xf - -C "${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 if [ -n "${CT_LIB_FILE}" ]; then
   172     lib_list=$("${sed}" -r -e ':loop; s/#.*//;'         \
   173                            -e 's/[[:space:]]+//g;'      \
   174                            -e 's/([^:])$/\1:/;'         \
   175                            -e '/$/N; s/\n//; tloop;'    \
   176                         "${CT_LIB_FILE}"
   177               )
   178     CT_LIB_LIST=$(echo "${CT_LIB_LIST}:${lib_list}"             \
   179                   |"${sed}" -r -e 's/:+/:/g; s/^:+//; s/:+$//;' \
   180                  )
   181 fi
   182 CT_LIB_LIST=$(echo "${CT_LIB_LIST}:${lib_list}"             \
   183               |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
   184              )
   185 if [ -n "${CT_LIB_LIST}" ]; then
   186     ${CT_PRINTF} "Installing forced libraries...\n"
   187     for name in ${CT_LIB_LIST}; do
   188         [ -z "${name}" ] && continue
   189         found=0
   190         for libname in "lib${name}.so" "${name}.so" "${name}"; do
   191             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   192             if do_add_lib "${libname}"; then
   193                 found=1
   194                 break
   195             fi
   196         done
   197         if [ ${found} -eq 0 ]; then
   198             echo "$myname: library '${libname}' not found!"
   199             [ "${CT_FORCE}" = y ] || exit 1
   200         fi
   201     done
   202 fi
   203 
   204 # Parse the working copy for executables and libraries
   205 still_needed=1
   206 while [ ${still_needed} -eq 1 ]; do
   207     ${CT_PRINTF} "Looping...\n"
   208     still_needed=0
   209     for f in $(find . -type f -exec file {} \;                                              \
   210                |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),'   \
   211                |cut -d ":" -f 1                                                             \
   212               ); do
   213         ${CT_PRINTF} "Scanning '%s'\n" "${f}"
   214         for libname in $("${CT_READELF}" -d "${f}"                              \
   215                          |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:'  \
   216                          |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'                 \
   217                         ); do
   218             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   219             if [    -e "lib/${libname}"     \
   220                  -o -e "usr/lib/${libname}" ]; then
   221                 ${CT_PRINTF} "    already present\n"
   222                 continue
   223             fi
   224             if do_add_lib "${libname}"; then
   225                 still_needed=1
   226             else
   227                 echo "$myname: library '${libname}' not found!"
   228             fi
   229         done
   230     done
   231 done
   232 
   233 # OK, we're done. Back off.
   234 popd >/dev/null