flatcar-scripts/install_toolchain
Michael Marineau 2ae0c30f4e fix(install_toolchain): Prevent tar from replacing lib symlinks
The cross toolchain doesn't have lib symlinks but this works because it
also doesn't install things to lib. However when this script manually
extracts the toolchain packages to BOARD_ROOT tar includes those empty
directories, replacing the symlinks that were previously there.

Longer term this really needs to go away, whatever build time is saved
by re-using the cross toolchain packages in BOARD_ROOT is not worth this
insane level of complexity it causes...
2013-07-22 21:42:57 -04:00

193 lines
6.2 KiB
Bash
Executable File

#!/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}' --exclude=lib \
'./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