blob: 38b68a353d2df12bfb1276556e06ccfa0893f3b2 [file] [log] [blame]
#!/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_boolean configure $FLAGS_TRUE \
"Update config files in <sysroot>/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"
DEFINE_string sysroot "" "The sysroot to install the toolchain for."
FLAGS_HELP="usage: $(basename $0) [flags]
Installs cross toolchain libraries into a sysroot. 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)
elif [[ "$pkg" = go ]] ; then
cpv=$(portageq match / dev-lang/go || 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() {
local board_version=$(get_variable "${SYSROOT_CACHE}" "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"
local go_ver="$3"
# 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
if [[ -n ${go_ver} ]]; then
sudo_append "$BOARD_PROFILE/package.provided" << EOF
dev-lang/go-${go_ver}
EOF
fi
}
# 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)
local go_ver=$(cross_get_version go)
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.
# Install libc libraries.
if [ "${CHOST}" != "$FLAGS_toolchain" ] ; then
local libc_atom="cross-${FLAGS_toolchain}/glibc-${libc_ver}"
local libc_path="${PKGDIR}/${libc_atom}.tbz2"
cmds=()
if [[ ! -e ${libc_path} ]]; then
cmds+=( "emerge --nodeps -gf =${libc_atom}" )
fi
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 \
|| echo 'WARNING: libc debug info not copied.' >&2"
)
sudo_multi "${cmds[@]}"
else
sudo emerge --oneshot --nodeps -k --root='${BOARD_ROOT}' \
=sys-libs/glibc-${libc_ver}
fi
if [[ ${FLAGS_configure} -eq ${FLAGS_TRUE} ]]; then
install_toolchain_in_provided "$gcc_ver" "$libc_ver" "$go_ver"
set_variable "${SYSROOT_CACHE}" "LIBC_VERSION" "${libc_ver}"
fi
}
set -u
if [[ -z "${FLAGS_sysroot}" ]]; then
die "--sysroot required."
fi
BOARD_ROOT="${FLAGS_sysroot}"
BOARD_ETC="${BOARD_ROOT}/etc"
BOARD_PROFILE="${BOARD_ETC}/portage/profile"
SYSROOT_CACHE="${BOARD_ROOT}/${SYSROOT_SETTINGS_FILE}"
sysroot_toolchain="$(get_sysroot_config "${FLAGS_sysroot}" "CHOST")"
: ${FLAGS_toolchain:=${sysroot_toolchain}}
if [ -z "${FLAGS_toolchain}" ]; then
die "No toolchain specified in the sysroot 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