diff --git a/install_toolchain b/install_toolchain new file mode 100755 index 0000000000..3ba0235462 --- /dev/null +++ b/install_toolchain @@ -0,0 +1,192 @@ +#!/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/." +DEFINE_boolean configure $FLAGS_TRUE \ + "Update config files in /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_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[@]}" + copy_gcc_libs "${BOARD_ROOT}" "cross-$FLAGS_toolchain/gcc-$gcc_ver" + 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. + sudo sed -i -e "/^LIBC_VERSION=/d" "$BOARD_SETUP" + 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 diff --git a/setup_board b/setup_board index f27738a3d4..eb48d94312 100755 --- a/setup_board +++ b/setup_board @@ -147,116 +147,8 @@ EOF sudo_multi "${cmds[@]}" } -# Checks whether the libc version installed in the board -# matches the one installed by the toolchain. -board_needs_libc_update() { - 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 -} - -# 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 -} - -install_toolchain_in_provided() { - local gcc_ver="$1" - local glibc_ver="$2" - # Tell portage that toolchain packages are already installed in the sysroot. - ( - echo sys-devel/gcc-$gcc_ver - echo sys-libs/glibc-$glibc_ver - ) | sudo_clobber "$BOARD_PROFILE/package.provided" -} - -# 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. - LIBC_TAR="glibc-${libc_ver}.tbz2" - - # Install libc libraries. - if [ "${CHOST}" != "$FLAGS_toolchain" ] ; then - LIBC_PATH="${PKGDIR}/cross-${FLAGS_toolchain}/${LIBC_TAR}" - sudo tar jxpf "${LIBC_PATH}" -C "${BOARD_ROOT}" ./usr/${FLAGS_toolchain} --strip-components=3 - sudo mkdir -p ${BOARD_ROOT}/usr/lib/debug - sudo 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." - GCC_PKG=cross-${FLAGS_toolchain}/gcc-$gcc_ver - - # TODO(asharif): Remove this hack after a while. - BOARD_GCC_DIR="${BOARD_ROOT}/usr/lib/gcc" - if [[ -L "${BOARD_GCC_DIR}" ]] ; then - sudo rm -f "${BOARD_GCC_DIR}" - fi - copy_gcc_libs "${BOARD_ROOT}" "cross-$FLAGS_toolchain/gcc-$gcc_ver" - 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'" - ) - sudo_multi "${cmds[@]}" - LIBC_PATH="${PKGDIR}/sys-libs/${LIBC_TAR}" - sudo emerge --oneshot --nodeps -k --root=${BOARD_ROOT} =sys-libs/glibc-${libc_ver} - # TODO: we have no debug - GCC_PKG=sys-devel/gcc-$gcc_ver - 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[@]}" - - install_toolchain_in_provided "$gcc_ver" "$libc_ver" - - # Configure new libc version in make.conf.board_setup. - sudo sed -i -e "/^LIBC_VERSION=/d" $BOARD_SETUP - echo "LIBC_VERSION=\"$libc_ver\"" | sudo_append $BOARD_SETUP +install_toolchain() { + "${GCLIENT_ROOT}/src/scripts/install_toolchain" --board="${BOARD_VARIANT}" } # Print contents of $BOARD_ETC/make.conf.board. This file sources make.conf @@ -456,11 +348,8 @@ if [ -d "${BOARD_ROOT}" ]; then warn "Not setting up board root. " warn "Use --force to clobber the board root and start again." fi - if board_needs_libc_update; then - # Update the users libc in their board if needed. - echo "Updating libc in the board." - install_toolchain_in_board - fi + # Update the users libc in their board if needed. + install_toolchain exit 0 fi else @@ -519,7 +408,7 @@ if ! ${HOST_BOARD}; then # We install the toolchain related bits after the BOARD_ROOT, BOARD_PROFILE # and BOARD_ETC directories have been created. if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then - install_toolchain_in_board + install_toolchain fi fi # Setup make.globals and the profile.