mirror of
https://github.com/flatcar/scripts.git
synced 2026-04-29 09:21:25 +02:00
If we try to setup multiple boards that use the same toolchain, we end up
deleting the package.{mask,keywords} files for the existing toolchain so
that we can detect if there are upgrades available. If there aren't, the
files don't get recreated (since we were relying on crossdev for it), and
the installed toolchain packages may no longer be directly reinstalled if
they aren't incidentally marked stable.
Normally this isn't an issue since people build for target boards only
rather than installing toolchains, but this breaks the sdk bot since it
sets up a bunch of bots and then tries to emerge all the toolchain pkgs
directly. With packages we've pinned that are unstable, portage fails:
The following keyword changes are necessary to proceed:
#required by =cross-arm-none-eabi/newlib-1.18.0 (argument)
>=cross-arm-none-eabi/newlib-1.18.0 **
So backup & restore the files in the update path rather than just blowing
them away. If we end up installing things anyways, crossdev will do the
right thing.
BUG=None
TEST=`cbuildbot chromiumos-sdk` passes
Change-Id: I6efc71179d6f897af91deaefe1ce6c62df10ebf6
Reviewed-on: https://gerrit.chromium.org/gerrit/16220
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
732 lines
25 KiB
Bash
Executable File
732 lines
25 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright (c) 2011 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.
|
|
|
|
# This script sets up a the sysroot for a particular target board.
|
|
|
|
# Load common CrOS utilities. Inside the chroot this file is installed in
|
|
# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
|
|
# location.
|
|
find_common_sh() {
|
|
local common_paths=(/usr/lib/crosutils $(dirname "$0"))
|
|
local path
|
|
|
|
SCRIPT_ROOT=
|
|
for path in "${common_paths[@]}"; do
|
|
local common="${path}/common.sh"
|
|
if ([ -r "${common}" ] && . "${common}" && [ -d "${SCRIPTS_DIR}" ]); then
|
|
SCRIPT_ROOT=${path}
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
find_common_sh
|
|
. "${SCRIPT_ROOT}/common.sh" || ! echo "Unable to load common.sh" || exit 1
|
|
. "${SRC_ROOT}/platform/dev/toolchain_utils.sh"
|
|
|
|
# Script must run inside the chroot
|
|
restart_in_chroot_if_needed "$@"
|
|
|
|
get_default_board
|
|
|
|
# Flags
|
|
DEFINE_string board "$DEFAULT_BOARD" \
|
|
"The name of the board to set up."
|
|
DEFINE_string build_root "/build" \
|
|
"The root location for board sysroots."
|
|
DEFINE_string board_overlay "" \
|
|
"Location of the board overlay."
|
|
DEFINE_string variant "" \
|
|
"Board variant."
|
|
DEFINE_string toolchain "" \
|
|
"Toolchain. For example: i686-pc-linux-gnu, armv7a-softfloat-linux-gnueabi"
|
|
DEFINE_boolean usepkg $FLAGS_TRUE \
|
|
"Use binary packages to bootstrap."
|
|
DEFINE_boolean force $FLAGS_FALSE \
|
|
"Force re-creating board root."
|
|
DEFINE_string binutils_version "2.21-r4" \
|
|
"Version of binutils to use."
|
|
DEFINE_string gcc_version "[stable]" \
|
|
"Version of gcc to use."
|
|
DEFINE_string libc_version "[stable]" \
|
|
"Version of libc to use."
|
|
DEFINE_string kernel_version "3.1" \
|
|
"Version of kernel headers to use."
|
|
DEFINE_boolean latest_toolchain $FLAGS_FALSE \
|
|
"Use the latest ebuild for all toolchain packages (gcc, binutils, libc, \
|
|
kernel). This overrides the other toolchain version options."
|
|
DEFINE_boolean default $FLAGS_FALSE \
|
|
"Set board to the default board in your chroot"
|
|
DEFINE_boolean fast ${DEFAULT_FAST} "Call many emerges in parallel"
|
|
DEFINE_string profile "" \
|
|
"The portage configuration profile to use. Profile must be located in overlay-board/profiles"
|
|
DEFINE_boolean quiet $FLAGS_FALSE \
|
|
"Don't print warnings when board already exists."
|
|
DEFINE_boolean skip_toolchain_update $FLAGS_FALSE \
|
|
"Don't update toolchain automatically."
|
|
|
|
# builds wrappers like equery-arm-generic.
|
|
# args:
|
|
# $1: command to wrap
|
|
# rest: extra arguments to pass to the command
|
|
generate_wrapper() {
|
|
local command="${1}"
|
|
shift
|
|
local extra_args="$@"
|
|
|
|
|
|
local target="/usr/local/bin/${command}-${BOARD_VARIANT}"
|
|
sudo_clobber "${target}" <<EOF
|
|
#!/bin/bash
|
|
|
|
export CHROMEOS_ROOT="$GCLIENT_ROOT"
|
|
export CHOST="$FLAGS_toolchain"
|
|
export PORTAGE_CONFIGROOT="$BOARD_ROOT"
|
|
export SYSROOT="$BOARD_ROOT"
|
|
if [ -z "\$PORTAGE_USERNAME" ]; then
|
|
export PORTAGE_USERNAME=\$(basename \$HOME)
|
|
fi
|
|
export ROOT="$BOARD_ROOT"
|
|
exec sudo -E ${command} ${extra_args} "\$@"
|
|
EOF
|
|
sudo chmod +rx ${target}
|
|
sudo chown root:root ${target}
|
|
eval ${command^^}_WRAPPER="${target}" # ${foo^^} returns toupper($foo)
|
|
echo created wrapper ${target}
|
|
}
|
|
|
|
generate_pkgconfig_wrapper() {
|
|
local target="/usr/local/bin/pkg-config-${BOARD_VARIANT}"
|
|
sudo_clobber "${target}" <<EOF
|
|
#!/bin/bash
|
|
|
|
PKG_CONFIG_LIBDIR="${BOARD_ROOT}/usr/lib/pkgconfig:\
|
|
${BOARD_ROOT}/usr/lib64/pkgconfig:\
|
|
${BOARD_ROOT}/usr/share/pkgconfig"
|
|
export PKG_CONFIG_LIBDIR
|
|
|
|
export PKG_CONFIG_SYSROOT_DIR="${BOARD_ROOT}"
|
|
|
|
exec pkg-config "\$@"
|
|
EOF
|
|
sudo chmod a+rx ${target}
|
|
sudo chown root:root ${target}
|
|
echo created wrapper pkg-config
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
# Check whether any new toolchain packages are available.
|
|
# Returns true if new toolchain packages are available and false otherwise.
|
|
toolchain_needs_update() {
|
|
local toolchain=$1
|
|
|
|
# If toolchain symlinks weren't created yet, we definitely need to update.
|
|
if [ ! -d /usr/local/portage/crossdev/cross-$toolchain ]; then
|
|
# NOTE: In this branch, the versions have not been resolved, and will
|
|
# be passed directly to crossdev. That works because crossdev understands
|
|
# '[stable]'.
|
|
# We cannot resolve the versions because the cross-$toolchain category is
|
|
# not yet set up.
|
|
return 0
|
|
fi
|
|
|
|
# Skip toolchain updates if requested.
|
|
if [ $FLAGS_skip_toolchain_update -eq $FLAGS_TRUE ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Unmask any ebuilds previously [un]masked by crossdev. crossdev will
|
|
# re-setup its masks appropriately the next time we run it.
|
|
local d
|
|
for d in package.{mask,keywords} ; do
|
|
sudo mv -f /etc/portage/${d}/{,.bak.}cross-${toolchain}
|
|
done
|
|
|
|
pkg_to_flag() {
|
|
[ "${1}" = "glibc" ] && echo "libc" || echo "$1"
|
|
}
|
|
|
|
local pkg
|
|
for pkg in gcc glibc binutils; do
|
|
local flagname=FLAGS_$(pkg_to_flag ${pkg})_version
|
|
if [ "${!flagname}" = "[stable]" ]; then
|
|
eval ${flagname}=$( \
|
|
portageq best_visible / "cross-$toolchain/${pkg}"| \
|
|
sed -e "s,cross-$toolchain/${pkg}-,,")
|
|
fi
|
|
done
|
|
|
|
local flags="--pretend --quiet --update"
|
|
local pkgs
|
|
if [ $FLAGS_usepkg -eq $FLAGS_TRUE ]; then
|
|
flags+=" --getbinpkg --usepkgonly"
|
|
fi
|
|
|
|
if [ $FLAGS_latest_toolchain -eq $FLAGS_TRUE ]; then
|
|
pkgs="cross-$toolchain/gcc"
|
|
pkgs+=" cross-$toolchain/binutils"
|
|
# For arm-none-eabi, there is no "glibc" or "linux-headers" packages.
|
|
if [[ "$toolchain" != "arm-none-eabi" ]] ; then
|
|
pkgs+=" cross-$toolchain/glibc"
|
|
pkgs+=" cross-$toolchain/linux-headers"
|
|
fi
|
|
elif [ $FLAGS_usepkg -eq $FLAGS_TRUE ]; then
|
|
pkgs="<=cross-$toolchain/gcc-$FLAGS_gcc_version"
|
|
pkgs+=" <=cross-$toolchain/binutils-$FLAGS_binutils_version"
|
|
if [[ "$toolchain" != "arm-none-eabi" ]] ; then
|
|
pkgs+=" <=cross-$toolchain/glibc-$FLAGS_libc_version"
|
|
pkgs+=" <=cross-$toolchain/linux-headers-$FLAGS_kernel_version"
|
|
fi
|
|
else
|
|
pkgs="=cross-$toolchain/gcc-$FLAGS_gcc_version"
|
|
pkgs+=" =cross-$toolchain/binutils-$FLAGS_binutils_version"
|
|
if [[ "$toolchain" != "arm-none-eabi" ]] ; then
|
|
pkgs+=" =cross-$toolchain/glibc-$FLAGS_libc_version"
|
|
pkgs+=" =cross-$toolchain/linux-headers-$FLAGS_kernel_version"
|
|
fi
|
|
fi
|
|
if [[ "$toolchain" != "arm-none-eabi" ]] ; then
|
|
pkgs+=" cross-$toolchain/gdb"
|
|
fi
|
|
ACCEPT_KEYWORDS="~* *" emerge $flags $pkgs | grep cross-$toolchain/
|
|
local ret=$?
|
|
|
|
# Restore the masks in case we don't end up running crossdev.
|
|
for d in package.{mask,keywords} ; do
|
|
sudo mv -f /etc/portage/${d}/{.bak.,}cross-${toolchain}
|
|
done
|
|
|
|
return ${ret}
|
|
}
|
|
|
|
uninstall_toolchain() {
|
|
local toolchain=$1
|
|
echo "Uninstalling the toolchain."
|
|
# Even if the uninstall fails, keep going. It's likely
|
|
# that it didn't exist in the first place.
|
|
yes | sudo crossdev -v -C $toolchain || true
|
|
}
|
|
|
|
# Build the toolchain with crossdev.
|
|
build_toolchain() {
|
|
local toolchain=$1
|
|
echo "Building the toolchain."
|
|
CROSS_ARGS="-v --target $toolchain -P --oneshot"
|
|
if [ $FLAGS_usepkg -eq $FLAGS_TRUE ]; then
|
|
# Grab the latest packages from the prebuilt server.
|
|
# --getbinpkg: Use packages from the prebuilt server.
|
|
# --usepkgonly: Always use prebuilts. Don't build from source.
|
|
# --without-headers: Don't build headers-only versions of packages for
|
|
# bootstrapping. Because we use binary packages, this
|
|
# isn't necessary.
|
|
CROSS_ARGS+=" -P --getbinpkg -P --usepkgonly --without-headers"
|
|
fi
|
|
if [ $FLAGS_latest_toolchain -ne $FLAGS_TRUE ]; then
|
|
CROSS_ARGS+=" --binutils $FLAGS_binutils_version"
|
|
CROSS_ARGS+=" --gcc $FLAGS_gcc_version"
|
|
if [[ "$toolchain" != "arm-none-eabi" ]]; then
|
|
# arm-none-eabi needs no version specification
|
|
CROSS_ARGS+=" --kernel $FLAGS_kernel_version"
|
|
CROSS_ARGS+=" --libc $FLAGS_libc_version"
|
|
fi
|
|
fi
|
|
|
|
CROSS_ARGS+=" --ex-gdb"
|
|
|
|
# TODO: remove this when crossdev upgrades.
|
|
if [[ "$toolchain" == "arm-none-eabi" ]]; then
|
|
CROSS_ARGS+=" --without-headers"
|
|
fi
|
|
|
|
sudo -E FEATURES="splitdebug ${FEATURES}" crossdev $CROSS_ARGS
|
|
}
|
|
|
|
# Get the version number of a toolchain package.
|
|
cross_get_version() {
|
|
local pkg="$1"
|
|
local cpv=""
|
|
if [[ "$CHOST" != "$FLAGS_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=$FLAGS_toolchain gcc-config -B || true)
|
|
cpv=$(portageq owners / $path | sed -e '/^\t/d')
|
|
else
|
|
cpv=$(portageq match / cross-$FLAGS_toolchain/$pkg || true)
|
|
fi
|
|
else
|
|
if [[ "$pkg" = binutils ]] ; then
|
|
cpv=$(portageq match / sys-devel/binutils || true)
|
|
elif [[ "$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 binutils_ver="$1"
|
|
local gcc_ver="$2"
|
|
local glibc_ver="$3"
|
|
# Tell portage that toolchain packages are already installed in the sysroot.
|
|
(
|
|
echo sys-devel/binutils-$binutils_ver
|
|
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 binutils_ver=$(cross_get_version binutils)
|
|
local gcc_ver=$(cross_get_version gcc)
|
|
local libc_ver=$(cross_get_version glibc)
|
|
if [[ -z "$binutils_ver" || -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
|
|
sudo mkdir -p ${BOARD_ROOT}/usr/lib64
|
|
sudo ln -sf ${BOARD_ROOT}/usr/lib64 ${BOARD_ROOT}/usr/lib
|
|
sudo mkdir -p ${BOARD_ROOT}/lib64
|
|
sudo ln -sf ${BOARD_ROOT}/lib64 ${BOARD_ROOT}/lib
|
|
LIBC_PATH="${PKGDIR}/sys-libs/${LIBC_TAR}"
|
|
sudo emerge --oneshot --nodeps -k --root=${BOARD_ROOT} =sys-libs/glibc-${libc_ver}
|
|
sudo mkdir -p ${BOARD_ROOT}/usr/lib/debug
|
|
# 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?
|
|
sudo cp -a /usr/include/rpcsvc/mount.h "${BOARD_ROOT}/usr/include/rpcsvc"
|
|
sudo cp -a /usr/include/rpcsvc/rquota.h "${BOARD_ROOT}/usr/include/rpcsvc"
|
|
sudo cp -a /usr/include/rpcsvc/nfs_prot.h "${BOARD_ROOT}/usr/include/rpcsvc"
|
|
sudo cp -a /usr/include/rpcsvc/yppasswd.h "${BOARD_ROOT}/usr/include/rpcsvc"
|
|
|
|
install_toolchain_in_provided "$binutils_ver" "$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
|
|
# from each overlay, and then calculates the prebuilt URLs based on the
|
|
# various binhost configuration files.
|
|
print_board_make_conf() {
|
|
echo "# AUTO-GENERATED FILE. DO NOT EDIT."
|
|
echo
|
|
echo "# Source make.conf from each overlay."
|
|
local boto_config=""
|
|
for overlay in $BOARD_OVERLAY_LIST; do
|
|
if [[ -f "$overlay/make.conf" ]]; then
|
|
echo source "$overlay/make.conf"
|
|
fi
|
|
if [[ -f "$overlay/googlestorage_account.boto" ]]; then
|
|
boto_config="$overlay/googlestorage_account.boto"
|
|
fi
|
|
done
|
|
local chromeos_overlay="$SRC_ROOT/private-overlays/chromeos-overlay"
|
|
if [[ -f "$chromeos_overlay/googlestorage_account.boto" ]]; then
|
|
boto_config="$chromeos_overlay/googlestorage_account.boto"
|
|
fi
|
|
local gsutil_cmd='gsutil cp \"${URI}\" \"${DISTDIR}/${FILE}\"'
|
|
echo
|
|
echo FETCHCOMMAND_GS="\"bash -c 'BOTO_CONFIG=$boto_config $gsutil_cmd'\""
|
|
echo RESUMECOMMAND_GS='"$FETCHCOMMAND_GS"'
|
|
echo
|
|
}
|
|
|
|
print_board_binhost_config() {
|
|
local binhost_dir="$CHROMIUMOS_OVERLAY/chromeos/binhost/target"
|
|
local preflight_binhost="$binhost_dir/$BOARD-PREFLIGHT_BINHOST.conf"
|
|
local chrome_binhost_suffix="LATEST_RELEASE_CHROME_BINHOST.conf"
|
|
local chrome_binhost="$binhost_dir/$BOARD-$chrome_binhost_suffix"
|
|
if [[ $ARCH = x86 && ! -f "$preflight_binhost" ]]; then
|
|
preflight_binhost="$binhost_dir/x86-generic-PREFLIGHT_BINHOST.conf"
|
|
fi
|
|
if [[ $ARCH = x86 && ! -f "$chrome_binhost" ]]; then
|
|
chrome_binhost="$binhost_dir/x86-generic-$chrome_binhost_suffix"
|
|
fi
|
|
local partner_overlay="$SRC_ROOT/private-overlays/chromeos-partner-overlay"
|
|
local internal_binhost_dir="$partner_overlay/chromeos/binhost/target"
|
|
local internal_binhost="$internal_binhost_dir/$BOARD-PREFLIGHT_BINHOST.conf"
|
|
|
|
cat <<'EOF'
|
|
# FULL_BINHOST is populated by the full builders. It is listed first because it
|
|
# is the lowest priority binhost. It is better to download packages from the
|
|
# preflight binhost because they are fresher packages.
|
|
PORTAGE_BINHOST="$FULL_BINHOST"
|
|
|
|
EOF
|
|
|
|
if [[ -f "$preflight_binhost" && -z "$IGNORE_PREFLIGHT_BINHOST" ]]; then
|
|
cat <<'EOF'
|
|
# PREFLIGHT_BINHOST is populated by the preflight builders. If the same
|
|
# package is provided by both the preflight and full binhosts, the package is
|
|
# downloaded from the preflight binhost.
|
|
EOF
|
|
echo source "$preflight_binhost"
|
|
echo 'PORTAGE_BINHOST="$PORTAGE_BINHOST $PREFLIGHT_BINHOST"'
|
|
echo
|
|
fi
|
|
|
|
if [[ -f "$internal_binhost" && -z "$IGNORE_PREFLIGHT_BINHOST" ]]; then
|
|
cat <<'EOF'
|
|
# The internal PREFLIGHT_BINHOST is populated by the internal preflight
|
|
# builders. It takes priority over the public preflight binhost.
|
|
EOF
|
|
echo source "$internal_binhost"
|
|
echo 'PORTAGE_BINHOST="$PORTAGE_BINHOST $PREFLIGHT_BINHOST"'
|
|
echo
|
|
fi
|
|
|
|
if [[ -f "$chrome_binhost" ]]; then
|
|
cat <<'EOF'
|
|
# LATEST_RELEASE_CHROME_BINHOST provides prebuilts for chromeos-chrome only.
|
|
EOF
|
|
echo source "$chrome_binhost"
|
|
echo 'PORTAGE_BINHOST="$PORTAGE_BINHOST $LATEST_RELEASE_CHROME_BINHOST"'
|
|
fi
|
|
}
|
|
|
|
# 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 'set -e' is specified before now.
|
|
set -e
|
|
|
|
if [ -z "$FLAGS_board" ] ; then
|
|
error "--board required."
|
|
exit 1
|
|
fi
|
|
|
|
# Before we can run any tools, we need to update chroot
|
|
UPDATE_ARGS=""
|
|
if [ "${FLAGS_fast}" -eq "${FLAGS_TRUE}" ]; then
|
|
UPDATE_ARGS+=" --fast"
|
|
else
|
|
UPDATE_ARGS+=" --nofast"
|
|
fi
|
|
if [ "${FLAGS_usepkg}" -eq "${FLAGS_TRUE}" ]; then
|
|
UPDATE_ARGS+=" --usepkg"
|
|
else
|
|
UPDATE_ARGS+=" --nousepkg"
|
|
fi
|
|
"${SRC_ROOT}/scripts"/update_chroot ${UPDATE_ARGS}
|
|
|
|
get_board_and_variant $FLAGS_board $FLAGS_variant
|
|
|
|
#
|
|
# Fetch the toolchain from the board overlay.
|
|
#
|
|
all_toolchains=( $(get_all_board_toolchains "${BOARD}") )
|
|
: ${FLAGS_toolchain:=${all_toolchains[0]}}
|
|
|
|
if [ -z "${FLAGS_toolchain}" ]; then
|
|
error "No toolchain specified in board overlay or on command line."
|
|
exit 1
|
|
fi
|
|
|
|
ARCH=$(get_board_arch "${BOARD}") || exit 1
|
|
|
|
case "$BOARD" in
|
|
*-host)
|
|
if [[ $FLAGS_usepkg -eq $FLAGS_TRUE ]]; then
|
|
die "host boards only support --nousepkg"
|
|
fi
|
|
HOST_BOARD=true
|
|
;;
|
|
*)
|
|
HOST_BOARD=false
|
|
esac
|
|
# Locations we will need
|
|
BOARD_ROOT="${FLAGS_build_root}/${BOARD_VARIANT}"
|
|
CHROMIUMOS_OVERLAY="/usr/local/portage/chromiumos"
|
|
CHROMIUMOS_CONFIG="${CHROMIUMOS_OVERLAY}/chromeos/config"
|
|
CHROMIUMOS_PROFILES="${CHROMIUMOS_OVERLAY}/profiles"
|
|
BOARD_ETC="${BOARD_ROOT}/etc"
|
|
BOARD_SETUP="${BOARD_ETC}/make.conf.board_setup"
|
|
BOARD_PROFILE="${BOARD_ETC}/portage/profile"
|
|
|
|
#
|
|
# Construct board overlay list.
|
|
#
|
|
BOARD_OVERLAY_LIST=$(cros_overlay_list \
|
|
--board "$BOARD" \
|
|
--board_overlay "$FLAGS_board_overlay" \
|
|
--variant "$VARIANT")
|
|
|
|
eval $(portageq envvar -v CHOST PKGDIR)
|
|
|
|
# Update all the toolchains that this board wants.
|
|
for toolchain in ${all_toolchains[@]} ; do
|
|
[[ "${CHOST}" == "${toolchain}" ]] && continue
|
|
|
|
toolchain_updated=${FLAGS_FALSE}
|
|
if toolchain_needs_update ${toolchain} ; then
|
|
toolchain_updated=${FLAGS_TRUE}
|
|
|
|
warn "Toolchain needs to be updated! Updating ${toolchain} ..."
|
|
uninstall_toolchain ${toolchain}
|
|
build_toolchain ${toolchain}
|
|
|
|
if [[ "${toolchain}" != arm* ]] ; then
|
|
info "Switching on gold as the default linker."
|
|
BINUTILS_VERSION=$(cross_get_version binutils | sed 's/-r[0-9]\+//g')
|
|
sudo binutils-config "${FLAGS_toolchain}-${BINUTILS_VERSION}-gold"
|
|
fi
|
|
fi
|
|
|
|
if [[ "${toolchain}" == "${FLAGS_toolchain}" ]] &&
|
|
[ -d "$BOARD_ROOT" ] && [ "$FLAGS_force" == "$FLAGS_FALSE" ] ; then
|
|
if [[ "${toolchain_updated}" == "${FLAGS_TRUE}" ]] ; then
|
|
# If the board root already exists, re-install the toolchain there.
|
|
install_toolchain_in_board
|
|
elif 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
|
|
fi
|
|
done
|
|
|
|
if [ -d "$BOARD_ROOT" ] ; then
|
|
if [[ $FLAGS_force -eq $FLAGS_TRUE ]]; then
|
|
echo "--force set. Re-creating $BOARD_ROOT..."
|
|
# Removal takes long. Make it asynchronous.
|
|
TEMP_DIR=`mktemp -d`
|
|
sudo mv $BOARD_ROOT $TEMP_DIR
|
|
sudo rm -rf $TEMP_DIR &
|
|
else
|
|
if ! $HOST_BOARD; then
|
|
print_board_make_conf | sudo_clobber $BOARD_ETC/make.conf.board
|
|
print_board_binhost_config | sudo_append $BOARD_ETC/make.conf.board
|
|
fi
|
|
if [[ $FLAGS_quiet -eq $FLAGS_FALSE ]]; then
|
|
warn "Board output directory '$BOARD_ROOT' already exists."
|
|
warn "Not setting up board root. "
|
|
warn "Use --force to clobber the board root and start again."
|
|
fi
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
sudo mkdir -p "$BOARD_ROOT" "${BOARD_ETC}" "${BOARD_PROFILE}"
|
|
|
|
if [ "${CHOST}" != "$FLAGS_toolchain" ] ; then
|
|
# TODO(cmasone): Do this more cleanly, if we figure out what "cleanly" means.
|
|
# Set up wrapper for pkg-config. Point a board-specific wrapper at the
|
|
# generic wrapper script created by crossdev-wrapper
|
|
sudo ln -sf "/usr/bin/cross-pkg-config" \
|
|
"/usr/bin/${FLAGS_toolchain}-pkg-config"
|
|
fi
|
|
|
|
# Setup the make.confs. We use the following:
|
|
# make.conf <- Overall target make.conf [arm, x86, etc. version]
|
|
# make.conf.board_setup <- Declares CHOST, ROOT, etc.
|
|
# make.conf.common <- Common settings across all targets
|
|
# make.conf.board <- Optional board-supplied make.conf
|
|
if ${HOST_BOARD}; then
|
|
sudo ln -sf "${CHROMIUMOS_CONFIG}/make.conf.${BOARD}" \
|
|
"${BOARD_ETC}/make.conf"
|
|
sudo cp -f "/etc/make.conf.host_setup" "${BOARD_ETC}/"
|
|
|
|
# Setting up symlinks for bootstrapping multilib.
|
|
# See http://crosbug.com/14498
|
|
sudo mkdir -p "${BOARD_ROOT}/usr/lib64" "${BOARD_ROOT}/lib64"
|
|
sudo ln -sf lib64 "${BOARD_ROOT}/lib"
|
|
sudo ln -sf lib64 "${BOARD_ROOT}/usr/lib"
|
|
|
|
# Copying some files for bootstrapping empty chroot.
|
|
# See http://crosbug.com/14499
|
|
sudo mkdir -p ${BOARD_ETC}/xml/
|
|
sudo cp /etc/xml/catalog ${BOARD_ETC}/xml/
|
|
sudo mkdir -p ${BOARD_ETC}/init.d/
|
|
sudo cp /etc/init.d/functions.sh ${BOARD_ETC}/init.d/
|
|
fi
|
|
sudo ln -sf "${CHROMIUMOS_CONFIG}/make.conf.common-target" \
|
|
"${BOARD_ETC}/make.conf.common"
|
|
cat <<EOF | sudo dd of="${BOARD_SETUP}" > /dev/null 2>&1
|
|
# Created by setup_board
|
|
CHOST="${FLAGS_toolchain}"
|
|
ROOT="${BOARD_ROOT}/"
|
|
BOARD_OVERLAY="${BOARD_OVERLAY_LIST}"
|
|
MAKEOPTS="-j${NUM_JOBS}"
|
|
PKG_CONFIG="pkg-config-${BOARD_VARIANT}"
|
|
BOARD_USE="${BOARD_VARIANT}"
|
|
EOF
|
|
if ! ${HOST_BOARD}; then
|
|
sudo ln -sf "${CHROMIUMOS_CONFIG}/make.conf.${ARCH}-target" \
|
|
"${BOARD_ETC}/make.conf"
|
|
print_board_make_conf | sudo_clobber $BOARD_ETC/make.conf.board
|
|
print_board_binhost_config | sudo_append $BOARD_ETC/make.conf.board
|
|
|
|
# We install the toolchain related bits after the BOARD_ROOT, BOARD_PROFILE
|
|
# and BOARD_ETC directories have been created.
|
|
install_toolchain_in_board
|
|
fi
|
|
# Setup make.globals and the profile.
|
|
sudo touch /etc/make.conf.user
|
|
sudo ln -sf /etc/make.globals "${BOARD_ROOT}/etc/make.globals"
|
|
sudo ln -sf /etc/make.conf.user "${BOARD_ROOT}/etc/make.conf.user"
|
|
|
|
# Select the profile to build based on the board and profile passed to
|
|
# setup_board. The developer can later change profiles by running
|
|
# cros_choose_profile manually.
|
|
if ! cros_choose_profile \
|
|
--board "${FLAGS_board}" \
|
|
--build_root "${FLAGS_build_root}" \
|
|
--board_overlay "${FLAGS_board_overlay}" \
|
|
--variant "${FLAGS_variant}" \
|
|
--profile "${FLAGS_profile}"; then
|
|
error "Selecting profile failed, removing incomplete board directory!"
|
|
sudo rm -rf "${BOARD_ROOT}"
|
|
exit 1
|
|
fi
|
|
|
|
|
|
for wrapper in 'emerge --root-deps' ebuild eclean equery portageq \
|
|
qcheck qfile qlist ; do
|
|
generate_wrapper $wrapper
|
|
done
|
|
|
|
generate_pkgconfig_wrapper
|
|
|
|
CROS_WORKON_WRAPPER="/usr/local/bin/cros_workon-${BOARD_VARIANT}"
|
|
cat <<EOF | sudo dd of="$CROS_WORKON_WRAPPER" > /dev/null 2>&1
|
|
#!/bin/bash
|
|
exec cros_workon --board ${BOARD_VARIANT} "\$@"
|
|
EOF
|
|
sudo chmod +x "$CROS_WORKON_WRAPPER"
|
|
|
|
#
|
|
# Emerge the kernel headers into the board build root.
|
|
#
|
|
EMERGE_FLAGS=""
|
|
if [[ $FLAGS_usepkg -eq $FLAGS_TRUE ]]; then
|
|
EMERGE_FLAGS="${EMERGE_FLAGS} --getbinpkg --usepkg"
|
|
fi
|
|
|
|
if ${HOST_BOARD}; then
|
|
EMERGE_CMD="emerge"
|
|
if [[ $FLAGS_fast -eq $FLAGS_TRUE ]]; then
|
|
EMERGE_CMD="${GCLIENT_ROOT}/chromite/bin/parallel_emerge"
|
|
fi
|
|
PACKAGES="system hard-host-depends world"
|
|
|
|
# First, rebuild all packages from scratch. This is needed to make sure
|
|
# we rebuild all chroot packages.
|
|
sudo -E $EMERGE_CMD --emptytree --with-bdeps=y $PACKAGES
|
|
sudo eclean -d packages
|
|
|
|
# Next, install our rebuilt packages into our separate root.
|
|
HOST_FLAGS="--root=$BOARD_ROOT --update --verbose --deep --root-deps"
|
|
HOST_FLAGS+=" --with-bdeps=y --newuse --jobs=$NUM_JOBS --usepkgonly"
|
|
sudo -E $EMERGE_CMD $HOST_FLAGS $PACKAGES
|
|
sudo cp -a "${PKGDIR}" $BOARD_ROOT/packages
|
|
|
|
# Install cross-compilers.
|
|
COMPILERS=$(equery l cross-*/* --format='=$cpv')
|
|
sudo -E $EMERGE_CMD $HOST_FLAGS --oneshot $COMPILERS
|
|
|
|
# Setup needed symlinks for cross-compilers.
|
|
sudo mkdir -p $BOARD_ROOT/usr/local/portage
|
|
sudo cp -a /usr/local/portage/crossdev $BOARD_ROOT/usr/local/portage
|
|
|
|
# Setup crossdev configuration for categories.
|
|
sudo cp -a /etc/portage/* $BOARD_ROOT/etc/portage
|
|
|
|
# The new chroot should have gcc for each target. Make sure that
|
|
# the latest one is correctly selected. Ignore cat errors as not
|
|
# all overlays will have a toolchain.conf.
|
|
ALL_OVERLAYS=$(cros_overlay_list --all_boards)
|
|
TARGETS=$(sed 's:#.*::' $(printf '%s/toolchain.conf ' ${ALL_OVERLAYS}) \
|
|
2>/dev/null | sort -u)
|
|
for target in ${TARGETS}; do
|
|
if [[ "${target}" != "arm-none-eabi" ]] ; then
|
|
# Install needed glibc tarball.
|
|
cross_target_path=/var/lib/portage/pkgs/cross-${target}
|
|
if [[ -e "$cross_target_path" ]] ; then
|
|
sudo mkdir -p ${BOARD_ROOT}${cross_target_path}
|
|
sudo cp -a ${cross_target_path}/glibc-* \
|
|
${BOARD_ROOT}${cross_target_path}
|
|
fi
|
|
fi
|
|
|
|
CURRENT_GCC="$(gcc-config -c ${target})"
|
|
sudo ROOT=${BOARD_ROOT} gcc-config ${CURRENT_GCC}
|
|
CURRENT_BINUTILS="$(binutils-config -c ${target})"
|
|
sudo ROOT=${BOARD_ROOT} binutils-config ${CURRENT_BINUTILS}
|
|
done
|
|
|
|
# Now cleanup paths referencing the ROOT from the *.la files.
|
|
sudo find $BOARD_ROOT -type f -name '*.la' | xargs sudo \
|
|
sed -i -e "s|$BOARD_ROOT/|/|g"
|
|
else
|
|
sudo -E "${EMERGE_WRAPPER}" ${EMERGE_FLAGS} chromeos-base/kernel-headers
|
|
fi
|
|
|
|
if [ $FLAGS_default -eq $FLAGS_TRUE ] ; then
|
|
echo $BOARD_VARIANT > "$GCLIENT_ROOT/src/scripts/.default_board"
|
|
fi
|
|
|
|
echo "Done!"
|
|
echo "The SYSROOT is: ${BOARD_ROOT}"
|
|
|
|
# NOTE: Printing the working-on ebuilds does not only serve the informative
|
|
# purpose. It also causes the ${BOARD_ROOT}/etc/portage/package.* files to be
|
|
# regenerated.
|
|
WORKING_ON=$(cros_workon --board=${FLAGS_board} list)
|
|
if [ -n "${WORKING_ON}" ]; then
|
|
echo
|
|
echo "Currently working on the following ebuilds for this board:"
|
|
echo "${WORKING_ON}"
|
|
fi
|