| #!/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." |
| |
| # 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}" |
| |
| # 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 |
| |
| 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) |
| |
| SYSROOT_EXISTS=false |
| 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 |
| # The sysroot exists. Take note so that we can exit early once the |
| # configuration has been updated. |
| SYSROOT_EXISTS=true |
| fi |
| else |
| # Regenerating configs w/out a board root doesn't make sense. |
| FLAGS_regen_configs=${FLAGS_FALSE} |
| fi |
| |
| # Setup the user specific 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 |
| |
| # 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. |
| # make.conf.user <- User specified parameters. |
| cmds=( |
| "mkdir -p '${BOARD_ROOT}' '${BOARD_ETC}' '${BOARD_PROFILE}' /usr/local/bin" |
| "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[@]}" |
| |
| # Generating the standard configuration file (make.conf.board_setup) for the |
| # sysroot. |
| 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 |
| |
| # Generate wrappers for portage helpers (equery, portageq, emerge, etc...). |
| # Those are used to generate make.conf.board. |
| cros_sysroot_utils create-wrappers --sysroot="${BOARD_ROOT}" \ |
| --friendlyname="${BOARD_VARIANT}" |
| |
| # 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 --profile "${FLAGS_profile}" \ |
| --board_root "${BOARD_ROOT}" --board "${FLAGS_board}"; then |
| sudo rm -rf --one-file-system "${BOARD_ROOT}" |
| die "Selecting profile failed, removing incomplete board directory!" |
| fi |
| |
| 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'" |
| "rm -r '${BOARD_ROOT}/usr/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/" |
| ) |
| sudo_multi "${cmds[@]}" |
| |
| EMERGE_CMD="${CHROMITE_BIN}/parallel_emerge" |
| TOOLCHAIN_PACKAGES=( |
| $("${CHROMITE_BIN}/cros_setup_toolchains" --show-packages host) |
| ) |
| # Sanity check we got some valid results. |
| if [[ ${#TOOLCHAIN_PACKAGES[@]} -eq 0 ]]; then |
| die_notrace "cros_setup_toolchains failed" |
| fi |
| 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 \ |
| "${TOOLCHAIN_PACKAGES[@]}" "${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 |
| conf="${CHROMIUMOS_CONFIG}/make.conf.generic-target" |
| sudo ln -sf "${conf}" "${BOARD_ETC}/make.conf" |
| EXTRA_ARGS=() |
| if [[ -n "${FLAGS_accept_licenses}" ]]; then |
| EXTRA_ARGS+=( --accepted-licenses="${FLAGS_accept_licenses}" ) |
| fi |
| sudo "${CHROMITE_BIN}/cros_sysroot_utils" generate-make-conf \ |
| --sysroot="${BOARD_ROOT}" --out-file="${BOARD_ETC}/make.conf.board" \ |
| "${EXTRA_ARGS[@]}" |
| |
| # We need to create make.conf.board in two steps as we need make.conf.board to |
| # exist before we can generate the binhost list. |
| EXTRA_ARGS=() |
| if [[ ${FLAGS_chrome_binhost_only} -eq ${FLAGS_TRUE} ]]; then |
| EXTRA_ARGS+=( --chrome-only ) |
| fi |
| if [[ ${FLAGS_reuse_pkgs_from_local_boards} -eq ${FLAGS_TRUE} ]]; then |
| EXTRA_ARGS+=( --local-only ) |
| fi |
| cros_sysroot_utils generate-binhosts --sysroot="${BOARD_ROOT}" \ |
| "${EXTRA_ARGS[@]}" | 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. |
| if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then |
| if [[ ${FLAGS_skip_board_pkg_init} -eq ${FLAGS_FALSE} ]]; then |
| "${GCLIENT_ROOT}/src/scripts/install_toolchain" --sysroot="${BOARD_ROOT}" |
| fi |
| |
| # If the sysroot already existed and we are not regenerating configuration, |
| # exit early. |
| if ${SYSROOT_EXISTS}; then |
| if [[ ${FLAGS_quiet} -eq ${FLAGS_FALSE} ]]; then |
| warn "Board output directory '$BOARD_ROOT' already exists." |
| warn "Exiting early." |
| warn "Use --force to clobber the board root and start again." |
| fi |
| exit 0 |
| fi |
| |
| # Call cros_workon to recreate symlinks to masked/unmasked packages |
| # currently worked on in case S{BOARD_ROOT} has been recreated |
| # (crbug.com/679831). |
| cros_workon --board="${BOARD_VARIANT}" list >/dev/null |
| |
| if [[ ${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 sys-libs/libcxxabi \ |
| sys-libs/libcxx |
| unset BASE_EMERGE_FLAGS |
| fi |
| 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 |