| #!/bin/bash |
| |
| # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| . "$(dirname "$0")/common.sh" || exit 1 |
| . "${SRC_ROOT}/platform/dev/toolchain_utils.sh" || exit 1 |
| |
| # Script must run inside the chroot |
| restart_in_chroot_if_needed "$@" |
| |
| assert_not_root_user |
| |
| # Developer-visible flags. |
| DEFINE_string board "$DEFAULT_BOARD" \ |
| "The name of the board to set up." |
| DEFINE_string board_root "" \ |
| "Path of the board root to install into. Defaults to /build/<board>." |
| DEFINE_boolean configure $FLAGS_TRUE \ |
| "Update config files in <board_root>/etc after installation." |
| DEFINE_boolean force $FLAGS_FALSE \ |
| "Install toolchain even if already up to date." |
| DEFINE_string toolchain "" \ |
| "Toolchain. For example: i686-pc-linux-gnu, armv7a-softfloat-linux-gnueabi" |
| |
| |
| FLAGS_HELP="usage: $(basename $0) [flags] |
| |
| Installs cross toolchain libraries into a board_root. This script is not |
| meant to be used by developers directly. Run at your own risk. |
| " |
| |
| show_help_if_requested "$@" |
| |
| # Parse command line flags |
| FLAGS "$@" || exit 1 |
| eval set -- "${FLAGS_ARGV}" |
| |
| # Only now can we die on error. shflags functions leak non-zero error codes, |
| # so will die prematurely if 'switch_to_strict_mode' is specified before now. |
| switch_to_strict_mode |
| |
| # Get the version number of a toolchain package. |
| cross_get_version() { |
| local pkg=$1 |
| local toolchain=${2:-${FLAGS_toolchain}} |
| local cpv |
| if [[ "$CHOST" != "${toolchain}" ]]; then |
| if [[ "$pkg" = "gcc" ]]; then |
| # Users can install multiple versions of gcc at once, so we need to call |
| # gcc-config to find out which installed version is selected. |
| local path=$(CTARGET="${toolchain}" gcc-config -B || true) |
| cpv=$(portageq owners / "$path" | sed -e '/^\t/d') |
| else |
| cpv=$(portageq match / "cross-${toolchain}/${pkg}" || true) |
| fi |
| else |
| if [[ "$pkg" = glibc ]] ; then |
| cpv=$(portageq match / sys-libs/glibc || true) |
| elif [[ "$pkg" = gcc ]] ; then |
| cpv=$(portageq match / sys-devel/gcc || true) |
| else |
| die "Unknown pkg ${pkg}" |
| fi |
| fi |
| local cp=$(echo $cpv | sed -e 's/-r[0-9]*$//; s/-[^-]*$//') |
| local result="${cpv#$cp-}" |
| local count="$(echo $result | wc -w)" |
| if [ "$count" -gt "1" ]; then |
| die "Multiple versions of $pkg installed" |
| elif [ "$count" -lt "1" ]; then |
| die "Cannot find $pkg" |
| fi |
| echo $result |
| } |
| |
| # Checks whether the libc version installed in the board |
| # matches the one installed by the toolchain. |
| board_needs_libc_update() { |
| if [[ ! -e "${BOARD_SETUP}" ]]; then |
| return 0 |
| fi |
| |
| local board_version=$(. "${BOARD_SETUP}"; echo "${LIBC_VERSION:-}") |
| local toolchain_version=$(cross_get_version glibc) |
| if [[ "${board_version}" = "${toolchain_version}" ]]; then |
| return 1 |
| fi |
| return 0 |
| } |
| |
| install_toolchain_in_provided() { |
| local gcc_ver="$1" |
| local glibc_ver="$2" |
| # Tell portage that toolchain packages are already installed in the sysroot. |
| sudo mkdir -p "$BOARD_PROFILE" |
| sudo_clobber "$BOARD_PROFILE/package.provided" << EOF |
| sys-devel/gcc-$gcc_ver |
| sys-libs/glibc-$glibc_ver |
| EOF |
| } |
| |
| # Install all of the stuff that depends on the toolchain versions |
| # into the board root. |
| install_toolchain_in_board() { |
| local cmds |
| local gcc_ver=$(cross_get_version gcc) |
| local libc_ver=$(cross_get_version glibc) |
| if [[ -z ${gcc_ver} || -z ${libc_ver} ]]; then |
| die "Cannot find toolchain to install into board root" |
| fi |
| echo "Installing the toolchain into the board root." |
| # Untar glibc to get most of the headers required to build. |
| local libc_tar="glibc-${libc_ver}.tbz2" |
| |
| # Install libc libraries. |
| if [ "${CHOST}" != "$FLAGS_toolchain" ] ; then |
| local libc_path="${PKGDIR}/cross-${FLAGS_toolchain}/${libc_tar}" |
| cmds=( |
| "tar jxpf '${libc_path}' -C '${BOARD_ROOT}' \ |
| './usr/${FLAGS_toolchain}' --strip-components=3" |
| "mkdir -p '${BOARD_ROOT}/usr/lib/debug'" |
| "tar jxpf '${libc_path}' -C '${BOARD_ROOT}/usr/lib/debug' \ |
| './usr/lib/debug/usr/${FLAGS_toolchain}' --strip-components=6 \ |
| || warn 'libc debug info not copied.'" |
| ) |
| # TODO(asharif): Remove this hack after a while. |
| local board_gcc_dir="${BOARD_ROOT}/usr/lib/gcc" |
| if [[ -L "${board_gcc_dir}" ]] ; then |
| cmd+=("rm -f '${board_gcc_dir}'") |
| fi |
| sudo_multi "${cmds[@]}" |
| else |
| cmds=( |
| "mkdir -p '${BOARD_ROOT}'{/usr,}/lib64 '${BOARD_ROOT}/usr/lib/debug'" |
| "ln -sfT '${BOARD_ROOT}/usr/lib64' '${BOARD_ROOT}/usr/lib'" |
| "ln -sfT '${BOARD_ROOT}/lib64' '${BOARD_ROOT}/lib'" |
| "emerge --oneshot --nodeps -k --root='${BOARD_ROOT}' \ |
| =sys-libs/glibc-${libc_ver}" |
| ) |
| sudo_multi "${cmds[@]}" |
| fi |
| |
| # Some header files are needed also for rpcbind (NFS support) |
| # TODO: Figure out a better way of doing this too? |
| cmds=( |
| "cp -a /usr/include/rpcsvc/mount.h '${BOARD_ROOT}/usr/include/rpcsvc'" |
| "cp -a /usr/include/rpcsvc/rquota.h '${BOARD_ROOT}/usr/include/rpcsvc'" |
| "cp -a /usr/include/rpcsvc/nfs_prot.h '${BOARD_ROOT}/usr/include/rpcsvc'" |
| "cp -a /usr/include/rpcsvc/yppasswd.h '${BOARD_ROOT}/usr/include/rpcsvc'" |
| ) |
| sudo_multi "${cmds[@]}" |
| |
| if [[ ${FLAGS_configure} -eq ${FLAGS_TRUE} ]]; then |
| install_toolchain_in_provided "$gcc_ver" "$libc_ver" |
| |
| # Configure new libc version in make.conf.board_setup. |
| if [[ -e ${BOARD_SETUP} ]]; then |
| sudo sed -i -e "/^LIBC_VERSION=/d" "${BOARD_SETUP}" |
| fi |
| echo "LIBC_VERSION=\"$libc_ver\"" | sudo_append "$BOARD_SETUP" |
| fi |
| } |
| |
| set -u |
| |
| if [ -z "$FLAGS_board" ] ; then |
| die "--board required." |
| fi |
| |
| get_board_and_variant $FLAGS_board "" |
| |
| BOARD_ROOT="${FLAGS_board_root:-/build/${BOARD_VARIANT}}" |
| BOARD_ETC="${BOARD_ROOT}/etc" |
| BOARD_SETUP="${BOARD_ETC}/make.conf.board_setup" |
| BOARD_PROFILE="${BOARD_ETC}/portage/profile" |
| |
| all_toolchains=( $(get_all_board_toolchains "${BOARD}") ) |
| : ${FLAGS_toolchain:=${all_toolchains[0]}} |
| |
| if [ -z "${FLAGS_toolchain}" ]; then |
| die "No toolchain specified in board overlay or on command line." |
| fi |
| |
| eval "$(portageq envvar -v CHOST PKGDIR)" |
| |
| if [[ ${FLAGS_force} -eq ${FLAGS_TRUE} ]] || \ |
| board_needs_libc_update; then |
| info "Updating libc in the board." |
| install_toolchain_in_board |
| else |
| info "Cross toolchain already up to date. Nothing to do." |
| fi |