scripts/populate.in
author Nate Case <ncase@xes-inc.com>
Tue Mar 23 19:27:41 2010 +0100 (2010-03-23)
changeset 1859 f4e17e0e2574
parent 1678 ac247da318a1
child 1860 ed94d8e12b63
permissions -rw-r--r--
scripts/populate: add option to use an alternate sysroot

Add a new command line option, "-r", which allows the user to specify
an alternate sysroot location to copy libraries from. This is useful
when using the toolchain in combination with a separate root filesystem,
or when working with multiple different root filesystems.

Signed-off-by: Nate Case <ncase@xes-inc.com>
     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     -r sysroot_dir
    42         use 'sysroot_dir' as the sysroot instead of the toolchain default
    43 
    44     -l name1[:name2[...]]
    45         Always add the specified shared library/ies name1, name2... from the
    46         toolchain (in the sys-root). Actual library names are searched as
    47         follows (where 'name' is replaced with the given name) in the
    48         sys-root directory:
    49           - libname.so
    50           - name.so
    51           - name
    52         If the file is found, then the SONAME of the library is used, and the
    53         library is copied with that name. If the library was not found, this
    54         yields an error (unless -f was given).
    55 
    56     -L file
    57         Read 'file' for a list of shared libraries to always add from the
    58         toolchain. The file should contain one library name per line; text
    59         after a # is ignored until the end of the line; spaces are ignored;
    60         empty lines are ignored. Libraries are searched for as with -l.
    61 
    62     -f  force execution: if destination directory already exists, it will be
    63         removed first; if a specified library (above) was not found, continue.
    64 
    65     -v  Be verbose. By default, populate is absolutely silent.
    66 
    67 _EOF_
    68 }
    69 
    70 CT_ROOT_SRC_DIR=
    71 CT_ROOT_DST_DIR=
    72 CT_LIB_LIST=
    73 CT_LIB_FILE=
    74 CT_FORCE=no
    75 CT_PRINTF=:
    76 OPTIND=1
    77 while getopts ":s:d:r:l:L:fvh" CT_OPT; do
    78     case "${CT_OPT}" in
    79         s)  CT_ROOT_SRC_DIR="${OPTARG}";;
    80         d)  CT_ROOT_DST_DIR="${OPTARG}";;
    81         r)  CT_SYSROOT_DIR="${OPTARG}";;
    82         l)  CT_LIB_LIST="${CT_LIB_LIST}:${OPTARG}";;
    83         L)  CT_LIB_FILE="${OPTARG}";;
    84         f)  CT_FORCE=y;;
    85         v)  CT_PRINTF=printf;;
    86         h)  doHelp
    87             exit 0
    88             ;;
    89         :)  echo "$myname: '-${OPTARG}' takes exactly one argument."
    90             exit 1
    91             ;;
    92         ?)  echo "$myname: unknown option '-${OPTARG}'."
    93             exit 1
    94             ;;
    95     esac
    96 done
    97 
    98 # Sanity checks
    99 if [ -z "${CT_ROOT_SRC_DIR}" -o -z "${CT_ROOT_DST_DIR}" ]; then
   100     doHelp
   101     exit 1
   102 fi
   103 if [ ! -d "${CT_ROOT_SRC_DIR}" ]; then
   104     echo "$myname: '${CT_ROOT_SRC_DIR}': no such file or directory"
   105     exit 1
   106 fi
   107 if [ ! -d "${CT_SYSROOT_DIR}" ]; then
   108     echo "$myname: '${CT_SYSROOT_DIR}': no such file or directory"
   109     exit 1
   110 fi
   111 if [ -d "${CT_ROOT_DST_DIR}" -a "${CT_FORCE}" != "y" ]; then
   112     echo "$myname: '${CT_ROOT_DST_DIR}': already exists"
   113     exit 1
   114 fi
   115 src_inode=$(stat -c '%i' "${CT_ROOT_SRC_DIR}/.")
   116 dst_inode=$(stat -c '%i' "${CT_ROOT_DST_DIR}/." 2>/dev/null || true)
   117 if [ "${src_inode}" -eq "$((dst_inode+0))" ]; then
   118     echo "$myname: source and destination are the same!"
   119     exit 1
   120 fi
   121 
   122 # Check existence of the forced libraries file
   123 if [ -n "${CT_LIB_FILE}" -a ! \( -f "${CT_LIB_FILE}" -a -r "${CT_LIB_FILE}" \) ]; then
   124     echo "$myname: forced libraries file '${CT_LIB_FILE}' not found!"
   125     exit 1
   126 fi
   127 
   128 # Get rid of potentially older destination directory
   129 rm -rf "${CT_ROOT_DST_DIR}"
   130 
   131 # Create the working copy
   132 mkdir -p "${CT_ROOT_DST_DIR}"
   133 
   134 # Make all path absolute
   135 CT_ROOT_SRC_DIR=$(cd "${CT_ROOT_SRC_DIR}"; pwd)
   136 CT_ROOT_DST_DIR=$(cd "${CT_ROOT_DST_DIR}"; pwd)
   137 
   138 # Populate the destination directory with files from the source directory
   139 pushd "${CT_ROOT_SRC_DIR}" >/dev/null
   140 cp -a . "${CT_ROOT_DST_DIR}"
   141 popd >/dev/null
   142 
   143 # A function do search for a library
   144 # Usage: do_add_lib libname
   145 # returns: 0 if library was found and added, !0 otherwise
   146 do_add_lib() {
   147     local libname="$1"
   148     local true_libname
   149     local dir
   150     local mode
   151 
   152     for dir in lib usr/lib; do
   153         ${CT_PRINTF} "    trying in '%s'" "${dir}"
   154         libfile="${CT_SYSROOT_DIR}/${dir}/${libname}"
   155         ${CT_PRINTF} ": '%s'\n" "${libfile}"
   156         if [ -e "${libfile}" ]; then
   157             mkdir -p "${dir}"
   158             true_libname=$("${CT_READELF}" -d "${libfile}"          \
   159                            |"${grep}" "Library soname:"             \
   160                            |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'   \
   161                           )
   162             case "${libfile}" in
   163                 */ld*)  mode=0755;;
   164                 *)      mode=0644;;
   165             esac
   166             ${CT_PRINTF} "      installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}"
   167             "${install}" -m "${mode}" "${libfile}" "${dir}/${true_libname}"
   168             return 0
   169             break
   170         fi
   171     done
   172     return 1
   173 }
   174 
   175 # We'll work in the copied rootfs
   176 pushd "${CT_ROOT_DST_DIR}" >/dev/null
   177 
   178 # First of, copy the forced libraries into the working copy
   179 if [ -n "${CT_LIB_FILE}" ]; then
   180     lib_list=$("${sed}" -r -e ':loop; s/#.*//;'         \
   181                            -e 's/[[:space:]]+//g;'      \
   182                            -e 's/([^:])$/\1:/;'         \
   183                            -e '/$/N; s/\n//; tloop;'    \
   184                         "${CT_LIB_FILE}"
   185               )
   186     CT_LIB_LIST=$(echo "${CT_LIB_LIST}:${lib_list}"             \
   187                   |"${sed}" -r -e 's/:+/:/g; s/^:+//; s/:+$//;' \
   188                  )
   189 fi
   190 CT_LIB_LIST=$(echo "${CT_LIB_LIST}:${lib_list}"             \
   191               |"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
   192              )
   193 if [ -n "${CT_LIB_LIST}" ]; then
   194     ${CT_PRINTF} "Installing forced libraries...\n"
   195     for name in ${CT_LIB_LIST}; do
   196         [ -z "${name}" ] && continue
   197         found=0
   198         for libname in "lib${name}.so" "${name}.so" "${name}"; do
   199             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   200             if do_add_lib "${libname}"; then
   201                 found=1
   202                 break
   203             fi
   204         done
   205         if [ ${found} -eq 0 ]; then
   206             echo "$myname: library '${libname}' not found!"
   207             [ "${CT_FORCE}" = y ] || exit 1
   208         fi
   209     done
   210 fi
   211 
   212 # Parse the working copy for executables and libraries
   213 still_needed=1
   214 while [ ${still_needed} -eq 1 ]; do
   215     ${CT_PRINTF} "Looping...\n"
   216     still_needed=0
   217     for f in $(find . -type f -exec file {} \;                                              \
   218                |"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB (executable|shared object),'   \
   219                |cut -d ":" -f 1                                                             \
   220               ); do
   221         ${CT_PRINTF} "Scanning '%s'\n" "${f}"
   222         for libname in $("${CT_READELF}" -d "${f}"                              \
   223                          |"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:'  \
   224                          |"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;'                 \
   225                         ); do
   226             ${CT_PRINTF} "  searching for '%s'\n" "${libname}"
   227             if [    -e "lib/${libname}"     \
   228                  -o -e "usr/lib/${libname}" ]; then
   229                 ${CT_PRINTF} "    already present\n"
   230                 continue
   231             fi
   232             if do_add_lib "${libname}"; then
   233                 still_needed=1
   234             else
   235                 echo "$myname: library '${libname}' not found!"
   236             fi
   237         done
   238     done
   239 done
   240 
   241 # OK, we're done. Back off.
   242 popd >/dev/null