blob: 11f1576c85fc5169a6766a178a58811e3af53faf [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"
# 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_boolean default $FLAGS_FALSE \
"Set board to the default board in your chroot"
DEFINE_boolean force $FLAGS_FALSE \
"Force re-creating board root."
DEFINE_boolean usepkg $FLAGS_TRUE \
"Use binary packages to bootstrap."
FLAGS_HELP="usage: $(basename $0) [flags]
setup_board sets up the sysroot for a particular board. This script is called
automatically when you run build_packages, so there is typically no need to
call it directly, unless you want to blow away your board (using --force).
"
show_help_if_requested "$@"
# The following options are advanced options, only available to those willing
# to read the source code. They are not shown in help output, since they are
# not needed for the typical developer workflow.
DEFINE_string accept_licenses "" \
"Licenses to append to the accept list."
DEFINE_string board_overlay "" \
"Location of the board overlay."
DEFINE_integer jobs -1 \
"How many packages to build in parallel at maximum."
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_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."
DEFINE_boolean skip_chroot_upgrade $FLAGS_FALSE \
"Don't run the chroot upgrade automatically; use with care."
DEFINE_string toolchain "" \
"Toolchain. For example: i686-pc-linux-gnu, armv7a-softfloat-linux-gnueabi"
DEFINE_string variant "" \
"Board variant."
DEFINE_boolean regen_configs ${FLAGS_FALSE} \
"Regenerate all config files (useful for modifying profiles w/out rebuild)."
DEFINE_boolean chrome_binhost_only $FLAGS_FALSE \
"Only fetch packages from the Chrome binhost."
DEFINE_boolean skip_board_pkg_init ${FLAGS_FALSE} \
"Don't emerge any packages during setup_board into the board root."
DEFINE_string board_root "" \
"Board root."
DEFINE_string brick "" "Brick to set up."
# The --reuse_pkgs_from_local_boards flag tells Portage to share binary
# packages between boards that are built locally, so that the total time
# required to build several boards is reduced. This flag is only useful
# when you are not able to use remote binary packages, since remote binary
# packages are usually more up to date than anything you have locally.
DEFINE_boolean reuse_pkgs_from_local_boards $FLAGS_FALSE \
"Bootstrap from local packages instead of remote packages."
install_toolchain() {
local toolchain_cmd="${GCLIENT_ROOT}/src/scripts/install_toolchain"
if [[ -n "${FLAGS_brick}" ]]; then
"${toolchain_cmd}" --brick="${FLAGS_brick}"
else
"${toolchain_cmd}" --board="${BOARD_VARIANT}" --board_root="${BOARD_ROOT}"
fi
}
# 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 gs_fetch_binpkg='/mnt/host/source/chromite/bin/gs_fetch_binpkg'
local gsutil_cmd=${gs_fetch_binpkg}' \"${URI}\" \"${DISTDIR}/${FILE}\"'
echo
echo "# Export boto_config as a variable so that we can easily look it up"
echo "# with portageq."
echo BOTO_CONFIG=\"$boto_config\"
echo
echo FETCHCOMMAND_GS="\"bash -c 'BOTO_CONFIG=$boto_config $gsutil_cmd'\""
echo RESUMECOMMAND_GS='"$FETCHCOMMAND_GS"'
echo
if [[ -n ${FLAGS_accept_licenses} ]]; then
echo "ACCEPT_LICENSE='${FLAGS_accept_licenses}'"
echo
fi
}
# Print the PORTAGE_BINHOST variable, suitable for inclusion in make.conf.board.
print_board_binhost_config() {
if [ "${FLAGS_reuse_pkgs_from_local_boards}" -eq "${FLAGS_TRUE}" ]; then
cros_generate_local_binhosts --board "${BOARD_VARIANT}"
echo 'PORTAGE_BINHOST="$LOCAL_BINHOST"'
return 0
fi
local binhost_dir="$CHROMIUMOS_OVERLAY/chromeos/binhost/target"
local chrome_binhost_suffix="LATEST_RELEASE_CHROME_BINHOST.conf"
local partner_overlay="$SRC_ROOT/private-overlays/chromeos-partner-overlay"
local internal_binhost_dir="$partner_overlay/chromeos/binhost/target"
# i_arch_map / e_arch_map: maps architectures to internal / external boards.
# i_kernel_map / e_kernel_map: maps kernels to internal / external boards.
declare -A i_arch_map e_arch_map e_kernel_map i_kernel_map \
e_chrome_arch_map i_chrome_arch_map
local chrome_binhost_base kernel
kernel=$(portageq-${BOARD_VARIANT} envvar CHROMEOS_KERNEL_SPLITCONFIG)
e_kernel_map=(['chromeos-exynos5']='daisy'
['chromiumos-tegra124']='daisy')
i_kernel_map=(['chromeos-exynos5']='daisy_skate'
['chromiumos-tegra124']='daisy_skate')
e_arch_map=(
['amd64']='amd64-generic'
['mips']='mipsel-o32-generic'
['x86']='x86-generic'
['arm']='arm-generic'
)
i_arch_map=(
['amd64']='lumpy'
['x86']='x86-alex'
['arm']='daisy_skate'
)
declare -A chrome_blacklist
chrome_blacklist=(
['falco']=yes
)
if has chrome_internal $(portageq-${BOARD_VARIANT} envvar USE); then
chrome_binhost_base=${internal_binhost_dir}
else
chrome_binhost_base=${binhost_dir}
fi
# External generic boards have no firmware or drivers, so their binhosts can
# be shared everywhere. The same isn't true for internal "generic" boards.
# For that reason, the internal "generic" boards can only be used for the
# Chrome binhost.
local e_generic="${e_kernel_map[${kernel:-none}]:-${e_arch_map[${ARCH}]:-}}"
local i_generic="${i_kernel_map[${kernel:-none}]:-${i_arch_map[${ARCH}]:-}}"
local e_chrome="" i_chrome=""
if has ozone $(portageq-${BOARD_VARIANT} envvar USE); then
# If ozone use flag is present, the grab Chrome prebuilts from a builder
# that uses the ozone use flags. (This use flag only affects Chrome.)
e_chrome_arch_map=(
['amd64']='amd64-generic_freon'
['arm']='arm-generic_freon'
)
i_chrome_arch_map=(
['amd64']='peppy'
['arm']='daisy_freon'
)
if has ozone_platform_default_dri $(portageq-${BOARD_VARIANT} envvar USE); then
i_chrome_arch_map['arm']='rush_ryu'
fi
e_chrome="${e_chrome_arch_map[${ARCH}]:-}"
i_chrome="${i_chrome_arch_map[${ARCH}]:-}"
fi
if [[ "${BOARD}" == "veyron" ]]; then
i_chrome="veyron_pinky"
fi
local board chrome_binhost internal_binhost preflight_binhost
for board in ${BOARD_VARIANT} ${i_chrome} ${e_chrome} \
${BOARD} ${i_generic} ${e_generic}; do
if [[ -n "${chrome_blacklist[${board}]}" ]]; then
continue
fi
if [[ -z ${chrome_binhost} || ! -f ${chrome_binhost} ||
-z $(source "${chrome_binhost}";
echo -n ${LATEST_RELEASE_CHROME_BINHOST}) ]]; then
chrome_binhost="${chrome_binhost_base}/${board}-${chrome_binhost_suffix}"
fi
done
for board in ${BOARD_VARIANT} ${BOARD} ${e_generic}; do
if [[ -z ${preflight_binhost} || ! -f ${preflight_binhost} ||
-z $(source "${preflight_binhost}";
echo -n ${PREFLIGHT_BINHOST}) ]]; then
preflight_binhost="${binhost_dir}/${board}-PREFLIGHT_BINHOST.conf"
fi
if [[ -z ${internal_binhost} || ! -f ${internal_binhost} ||
-z $(source "${internal_binhost}";
echo -n ${PREFLIGHT_BINHOST}) ]]; then
internal_binhost="${internal_binhost_dir}/${board}-PREFLIGHT_BINHOST.conf"
fi
done
if [ "${FLAGS_chrome_binhost_only}" -eq "${FLAGS_TRUE}" ]; then
echo source "$chrome_binhost"
echo 'PORTAGE_BINHOST="$LATEST_RELEASE_CHROME_BINHOST"'
else
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
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 'switch_to_strict_mode' is specified before now.
switch_to_strict_mode
if [[ -z "${FLAGS_board}" ]] && [[ -z "${FLAGS_brick}" ]]; then
die "--board or --brick required."
elif [[ -n "${FLAGS_brick}" ]]; then
# Clear the board value if brick was provided (backward compatibility).
[[ -z "${FLAGS_board}" ]] || warn "--brick was used, ignoring --board value"
FLAGS_board=
fi
get_board_and_variant "${FLAGS_board}" "${FLAGS_variant}" "${FLAGS_brick}"
#
# Construct board overlay list.
#
if [[ -n "${FLAGS_brick}" ]]; then
BOARD_OVERLAY_LIST=$(cros_list_overlays --brick "${FLAGS_brick}")
else
BOARD_OVERLAY_LIST=$(cros_list_overlays \
--board "${BOARD_VARIANT}" \
--board_overlay "${FLAGS_board_overlay}")
fi
# Before we can run any tools, we need to update chroot
UPDATE_ARGS="--toolchain_boards=${BOARD}"
if [ "${FLAGS_usepkg}" -eq "${FLAGS_TRUE}" ]; then
UPDATE_ARGS+=" --usepkg"
else
UPDATE_ARGS+=" --nousepkg"
fi
if [[ "${FLAGS_jobs}" -ne -1 ]]; then
UPDATE_ARGS+=" --jobs=${FLAGS_jobs}"
fi
if [[ "${FLAGS_skip_toolchain_update}" -eq "${FLAGS_TRUE}" ]] \
|| [[ -n "${FLAGS_brick}" ]]; then
UPDATE_ARGS+=" --skip_toolchain_update"
fi
if [ "${FLAGS_skip_chroot_upgrade}" -eq "${FLAGS_FALSE}" ] ; then
"${SRC_ROOT}/scripts"/update_chroot ${UPDATE_ARGS}
fi
#
# Fetch the toolchain from the board overlay.
#
all_toolchains=( $(get_all_board_toolchains "${FLAGS_brick:-${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 "${FLAGS_brick:-${BOARD}}") || exit 1
case "$BOARD" in
*-host)
if [[ $FLAGS_usepkg -eq $FLAGS_TRUE ]]; then
die_notrace "host boards only support --nousepkg"
fi
HOST_BOARD=true
;;
*)
HOST_BOARD=false
esac
# Locations we will need
BOARD_ROOT="${FLAGS_board_root:-/build/${BOARD_VARIANT}}"
CROSSDEV_OVERLAY="/usr/local/portage/crossdev"
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"
eval $(portageq envvar -v CHOST PKGDIR)
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 --one-file-system "${TEMP_DIR}" &
else
if ! ${HOST_BOARD}; then
{ print_board_make_conf; print_board_binhost_config; } | \
sudo_clobber $BOARD_ETC/make.conf.board
fi
if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then
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
if [[ ${FLAGS_skip_board_pkg_init} -eq ${FLAGS_FALSE} ]]; then
# Update the users libc in their board if needed.
install_toolchain
fi
exit 0
fi
fi
else
# Regenerating configs w/out a board root doesn't make sense.
FLAGS_regen_configs=${FLAGS_FALSE}
fi
cmds=(
"mkdir -p '${BOARD_ROOT}' '${BOARD_ETC}' '${BOARD_PROFILE}' /usr/local/bin"
)
# 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.board <- Optional board-supplied make.conf
if ${HOST_BOARD}; then
cmds+=(
"ln -sf '${CHROMIUMOS_CONFIG}/make.conf.${BOARD}' \
'${BOARD_ETC}/make.conf'"
"cp -f '/etc/make.conf.host_setup' '${BOARD_ETC}/'"
# Setting up symlinks for bootstrapping multilib.
# See http://crosbug.com/14498
"mkdir -p '${BOARD_ROOT}'{/usr,}/lib64"
"ln -sfT lib64 '${BOARD_ROOT}/lib'"
"ln -sfT lib64 '${BOARD_ROOT}/usr/lib'"
# Copying some files for bootstrapping empty chroot.
# See http://crosbug.com/14499
"mkdir -p '${BOARD_ETC}'/{init.d,xml}"
"cp /etc/xml/catalog '${BOARD_ETC}'/xml/"
"cp /etc/init.d/functions.sh '${BOARD_ETC}'/init.d/"
)
fi
sudo_multi "${cmds[@]}"
SAVED_VERSION=
if [[ ${FLAGS_regen_configs} -eq ${FLAGS_TRUE} ]]; then
SAVED_VERSION=$(grep -s ^LIBC_VERSION= ${BOARD_SETUP} || true)
fi
if [[ -n "${FLAGS_brick}" ]]; then
cros_sysroot_utils generate-config --sysroot="${BOARD_ROOT}" \
--brick="${FLAGS_brick}" --out-file="${BOARD_SETUP}"
else
cros_sysroot_utils generate-config --sysroot="${BOARD_ROOT}" \
--board="${FLAGS_board}" --out-file="${BOARD_SETUP}"
fi
printf "\n%s\n" "${SAVED_VERSION}" | sudo_append "${BOARD_SETUP}"
if ! ${HOST_BOARD}; then
for a in ${ARCH} generic; do
conf="${CHROMIUMOS_CONFIG}/make.conf.${a}-target"
if [[ -e ${conf} ]]; then
sudo ln -sf "${conf}" "${BOARD_ETC}/make.conf"
break
fi
done
print_board_make_conf | sudo_clobber $BOARD_ETC/make.conf.board
# 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} && \
${FLAGS_skip_board_pkg_init} -eq ${FLAGS_FALSE} ]]; then
install_toolchain
fi
fi
# Setup the profile.
if [[ ! -s /etc/make.conf.user ]]; then
sudo_clobber /etc/make.conf.user <<\EOF
# This file is useful for doing global (chroot and all board) changes.
# Tweak emerge settings, ebuild env, etc...
#
# Make sure to append variables unless you really want to clobber all
# existing settings. e.g. You most likely want:
# FEATURES="${FEATURES} ..."
# USE="${USE} foo"
# and *not*:
# USE="foo"
#
# This also is a good place to setup ACCEPT_LICENSE.
EOF
fi
cmds=(
"ln -sf /etc/make.conf.user '${BOARD_ROOT}/etc/make.conf.user'"
"mkdir -p '${BOARD_ROOT}/etc/portage/hooks'"
)
for d in "${SCRIPTS_DIR}"/hooks/*; do
cmds+=( "ln -sfT '${d}' '${BOARD_ROOT}/etc/portage/hooks/${d##*/}'" )
done
sudo_multi "${cmds[@]}"
# 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}" \
--board_overlay "${FLAGS_board_overlay}" \
--variant "${FLAGS_variant}" \
--brick "${FLAGS_brick}" \
--profile "${FLAGS_profile}" \
--board_root "${BOARD_ROOT}"; then
error "Selecting profile failed, removing incomplete board directory!"
sudo rm -rf --one-file-system "${BOARD_ROOT}"
exit 1
fi
cros_sysroot_utils create-wrappers --sysroot="${BOARD_ROOT}" \
--toolchain="${FLAGS_toolchain}" --friendlyname="${BOARD_VARIANT}"
if ${HOST_BOARD}; then
EMERGE_CMD="${GCLIENT_ROOT}/chromite/bin/parallel_emerge"
PACKAGES="system virtual/target-sdk 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 --select=y $PACKAGES
sudo cp -a "${PKGDIR}" $BOARD_ROOT/packages
# Copy our chroot version into the newly packaged chroot.
sudo cp -a "${CHROOT_VERSION_FILE}" "${BOARD_ROOT}${CHROOT_VERSION_FILE}"
# 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
# Now that the portageq-* wrappers have been created, we can add the binhost
# config to make.conf.board.
print_board_binhost_config | sudo_append $BOARD_ETC/make.conf.board
if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} && \
${FLAGS_skip_board_pkg_init} -eq ${FLAGS_FALSE} ]]; then
# Emerge the kernel headers into the board build root. Use rdeps to
# avoid pulling any spurious DEPEND things in that we don't care about.
BASE_EMERGE_FLAGS="--select --quiet --root-deps=rdeps"
if [[ "${FLAGS_usepkg}" -eq "${FLAGS_TRUE}" ||
"${FLAGS_reuse_pkgs_from_local_boards}" -eq "${FLAGS_TRUE}" ]]; then
BASE_EMERGE_FLAGS+=" --getbinpkg --usepkg"
fi
sudo -E "emerge-${BOARD_VARIANT}" ${BASE_EMERGE_FLAGS} \
sys-kernel/linux-headers sys-libs/gcc-libs
unset BASE_EMERGE_FLAGS
fi
fi
if [ $FLAGS_default -eq $FLAGS_TRUE ] ; then
echo $BOARD_VARIANT > "$GCLIENT_ROOT/src/scripts/.default_board"
fi
command_completed
echo "Done!"
echo "The SYSROOT is: ${BOARD_ROOT}"
if [[ -n ${FLAGS_board_root} ]]; then
# cros_workon do not support board_root.
exit 0
fi
# 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=${BOARD_VARIANT} list)
if [ -n "${WORKING_ON}" ]; then
echo
echo "Currently working on the following ebuilds for this board:"
echo "${WORKING_ON}"
fi