Add install_toolchain script.

Move cross toolchain library install code out of setup_board to a
separate script, and have setup_board use it.

The install_toolchain script will be used by the builders to set up
a separate sysroot (distinct from the /build/<board> root), as part of
the Simplified Chrome Workflow (goto/simple-chrome).

BUG=chromium-os:36299
TEST=locally, trybots.

Change-Id: I88c355f1798da71ead9370a82365304dbf311504
Reviewed-on: https://gerrit.chromium.org/gerrit/38156
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Ready: Ryan Cui <rcui@chromium.org>
Tested-by: Ryan Cui <rcui@chromium.org>
This commit is contained in:
Ryan Cui 2012-11-15 12:25:20 -08:00 committed by Gerrit
parent 4c537f1ebe
commit dbac9554aa
2 changed files with 197 additions and 116 deletions

192
install_toolchain Executable file
View File

@ -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/<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_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

View File

@ -147,116 +147,8 @@ EOF
sudo_multi "${cmds[@]}" sudo_multi "${cmds[@]}"
} }
# Checks whether the libc version installed in the board install_toolchain() {
# matches the one installed by the toolchain. "${GCLIENT_ROOT}/src/scripts/install_toolchain" --board="${BOARD_VARIANT}"
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
} }
# Print contents of $BOARD_ETC/make.conf.board. This file sources make.conf # 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 "Not setting up board root. "
warn "Use --force to clobber the board root and start again." warn "Use --force to clobber the board root and start again."
fi fi
if board_needs_libc_update; then
# Update the users libc in their board if needed. # Update the users libc in their board if needed.
echo "Updating libc in the board." install_toolchain
install_toolchain_in_board
fi
exit 0 exit 0
fi fi
else else
@ -519,7 +408,7 @@ if ! ${HOST_BOARD}; then
# We install the toolchain related bits after the BOARD_ROOT, BOARD_PROFILE # We install the toolchain related bits after the BOARD_ROOT, BOARD_PROFILE
# and BOARD_ETC directories have been created. # and BOARD_ETC directories have been created.
if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then
install_toolchain_in_board install_toolchain
fi fi
fi fi
# Setup make.globals and the profile. # Setup make.globals and the profile.