| #!/bin/bash | |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| #### CATEGORY=Build | |
| #### PREBUILTS=${PREBUILT_GN} ${PREBUILT_NINJA} ${PREBUILT_PYTHON3} | |
| ### set up a build directory | |
| ## usage: fx set PRODUCT.BOARD [--with GNLABEL1,GNLABEL2,...] | |
| ## [--release] [--args ARG] [--variant VARIANT] | |
| ## [--with-test GNLABEL1,GNLABEL2,...] | |
| ## | |
| ## where PRODUCT is an entry from `//products` or `//vendor/*/products` and | |
| ## BOARD is an entry from `//boards` or `//vendor/*/boards`. Use the | |
| ## `fx list-products` and `fx list-boards` commands to see a list of | |
| ## possible products and boards (respectively). See the README.md in those | |
| ## directories for a description of the various options. | |
| ## | |
| ## Use `fx --dir BUILD_DIR set` to specify the build directory. If it begins with | |
| ## `//` or `out/` then it's taken as relative to FUCHSIA_DIR. Otherwise it should | |
| ## be an absolute path or a path relative to the current working directory that | |
| ## winds up in `FUCHSIA_DIR/out`. It defaults to `out/default`. | |
| ## | |
| ## This command stores the location of the build directory in the //.fx-build-dir | |
| ## file, which causes subsequent `fx` commands to use that build directory. Use | |
| ## `fx use` to switch build directories. | |
| ## | |
| ## This is a wrapper around running `gn gen --check=system BUILD_DIR --args ...`. | |
| ## If GN fails with an error, `fx set` does not change anything. | |
| ## | |
| ## optional arguments: | |
| ## --args Additional argument to pass to gn. If the --args | |
| ## argument is given multiple times, all the specified | |
| ## arguments are passed to gn. | |
| ## N.B. Arguments must be expressed using GN's syntax. | |
| ## In particular this means that for strings they must | |
| ## be quoted with double-quotes, and the quoting must | |
| ## survive, for example, the shell. Thus when passing | |
| ## an argument that takes a string, pass it with | |
| ## something like --args=foo='"bar"'. E.g., | |
| ## bash$ fx set core.x64 --args=foo='"bar"' | |
| ## More complicated arguments, e.g., lists, require | |
| ## their own special syntax. See GN documentation | |
| ## for the syntax of each kind of argument. | |
| ## --ccache|--no-ccache Whether to use ccache during the build. Ccache attempts | |
| ## to make builds faster by caching build artifacts. | |
| ## Defaults to detecting whether the CCACHE_DIR environment | |
| ## variable is set to a directory. | |
| ## --fuzz-with Pass a sanitizer name, e.g. "--fuzz-with asan" to | |
| ## enable ALL supporting fuzzers. Use --variant for | |
| ## individual fuzzers, e.g. "--variant asan-fuzzer/foo". | |
| ## --rbe-mode Use a preset RBE configuration. | |
| ## Valid options: auto, off, workstation, cloudtop, | |
| ## legacy_default, remote_cache_only, low_bandwidth. | |
| ## 'auto' chooses one of the other options for you. | |
| ## See also build/toolchain/rbe_modes.gni for details. | |
| ## Default: auto | |
| ## --cxx-rbe If set, use reclient (RBE) to remotely compile and | |
| ## cache C++ targets. | |
| ## This overrides the C++ setting in --rbe-mode. | |
| ## Default: enabled on linux-x64, disabled elsewhere. | |
| ## --link-rbe If set, use reclient (RBE) to remotely link and | |
| ## cache C++ targets. | |
| ## This overrides the linking setting in --rbe-mode. | |
| ## Default: disabled | |
| ## --rust-rbe If set, use the remote backend (RBE) service for | |
| ## building and caching Rust targets. | |
| ## This overrides the Rust setting in --rbe-mode. | |
| ## Default: disabled | |
| ## --bazel-rbe If set, allow bazel to build remotely on RBE. | |
| ## This overrides the Bazel setting in --rbe-mode. | |
| ## Default: disabled | |
| ## --ide Pass --ide=VALUE to gn when generating to create project | |
| ## files usable with that IDE. Useful values include "vs" | |
| ## for Visual Studio or "xcode" for Xcode. | |
| ## --json-ide-script Pass --json-ide-script=python_script to gn which runs | |
| ## the given python script after the JSON project file is | |
| ## generated when using --ide json. The path to the project | |
| ## file is given as the first argument to the script. | |
| ## The script may be a path or a gn label. | |
| ## --netboot Ensure that a network ramboot image is always built. | |
| ## --compilation-mode Sets the `compilation_mode` to the specified value. | |
| ## Valid values are "release", "balanced", "debug", and "sanitizer". | |
| ## Defaults to "balanced". | |
| ## --release Shortcut for `--compilation-mode release`. | |
| ## --balanced Shortcut for `--compilation-mode balanced`, which is | |
| ## less optimized than `"release"`, but still has some | |
| ## optimizations enabled. | |
| ## --debug Shortcut for `--compilation-mode debug`. | |
| ## --sanitizer Shortcut for `--compilation-mode sanitizer`. | |
| ## --variant Selects which runtime variant to use (e.g., asan) by | |
| ## passing a `select_variant=[VARIANT*,...]` argument | |
| ## to gn that collects all the --variant arguments in | |
| ## order. Variants are normal builds in most respects, | |
| ## but allow users to test different runtime settings | |
| ## for either the whole build or for a specific target. | |
| ## This can be specified by passing the variant name | |
| ## to this argument (e.g. `--variant asan`) for the | |
| ## former, or the variant name and the target name | |
| ## separated by a slash (e.g. `--variant asan/my_test`) | |
| ## for the latter. | |
| ## --with GNLABEL Labels of additional packages to include in the | |
| ## 'universe' set of available packages. These packages | |
| ## can be run ephemerally. Multiple labels can be | |
| ## provided delimited by commas or the --with argument | |
| ## can be provided multiple times. | |
| ## --with-test GNLABEL Labels of additional tests to include in the build. | |
| ## When run by 'fx test', these tests are ephemeral. To | |
| ## add host tests, either use '--with-host' qualify the | |
| ## the label with the host toolchain, or add a group | |
| ## which depends on the host tests in the host | |
| ## toolchain. Multiple labels can be provided delimited | |
| ## by commas or the '--with-test' argument can be | |
| ## provided multiple times. | |
| ## --with-host GNLABEL Labels of additional host-only targets to be | |
| ## produced by the build. Multiple labels can be | |
| ## provided delimited by commas or the --with-host | |
| ## argument can be provided multiple times. | |
| ## --cargo-toml-gen Enable generation of Cargo.toml files. | |
| ## --include-clippy[=true|false] Run clippy as part of `fx build` (defaults to `true`) | |
| ## --fint-params-path Used to specify a path to a fint parameters file, as | |
| ## selected by `fx repro`. If set, no other flags that | |
| ## influence the build configuration should be set. | |
| ## --dev Always recompile fx-set from source. | |
| ## --assembly-override Pairs of ASSEMBLY_TARGET=OVERRIDE_TARGET labels to use | |
| ## to define the developer assembly overrides targets to | |
| ## use with the given assembly target. Can be provided | |
| ## multiple times with different ASSEMBLY_TARGET labels. | |
| ## if the 'ASSEMBLY_TARGET=' portion is omitted, the | |
| ## "main" assembly for the product will be assumed. | |
| ## --main-pb Build label for the main product bundle to work with. | |
| ## Useful for multi-product builds. | |
| ## --resultstore Enable ResultStore uploading locally for the newly set up | |
| ## build directory. | |
| ## --no-change-env Configure the build graph without modifying global .fx-build-dir | |
| ## or out/default symlinks. Keep environment pristine. | |
| ## | |
| ## Example: | |
| ## | |
| ## $ fx set core.x64 --with-test //bundles/tests | |
| ## -> build directory: out/core.x64 | |
| ## board: //boards/x64.gni | |
| ## product: //products/core.gni | |
| ## developer_test_labels: //bundles/tests (all test packages) | |
| # shellcheck source=/dev/null | |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $? | |
| set -e | |
| function main { | |
| fx-standard-switches "$@" | |
| # Check if the --dev flag is set. If it is, then we'll always build fx-set | |
| # from source. Also intercept --resultstore to enable it on success. | |
| local dev=false | |
| local enable_resultstore=false | |
| for arg; do | |
| shift | |
| if [ "$arg" = --dev ]; then | |
| dev=true | |
| continue | |
| fi | |
| if [ "$arg" = --resultstore ]; then | |
| enable_resultstore=true | |
| continue | |
| fi | |
| # Include every arg besides --dev and --resultstore in the args we pass to fx-set. | |
| set -- "$@" "$arg" | |
| done | |
| if [[ "$(uname)" == [Dd]arwin ]]; then | |
| fx-error "Building Fuchsia on macOS is not supported." | |
| fx-error "Please see http://go/local-platform-support-prd for details." | |
| exit 1 | |
| fi | |
| # Cache the compiled executable for later invocations. | |
| readonly exe_path="${FX_CACHE_DIR}/fx-set" | |
| readonly revision_file="${FX_CACHE_DIR}/fx-set-revision" | |
| local current_revision | |
| current_revision="$(git --no-optional-locks -C "$FUCHSIA_DIR" rev-parse HEAD)" | |
| # Determine whether we need to rebuild the fx-set executable. We'll only | |
| # rebuild if the --dev flag is set, or if the cached version of fx-set was | |
| # built at a revision other than the current revision. We determine that by | |
| # storing the current HEAD of fuchsia.git in a cached version file whenever | |
| # we build fx-set, and then we rebuild if the current HEAD differs from the | |
| # revision referenced in the cached file. | |
| local should_rebuild=true | |
| if ! $dev && [ -f "$exe_path" ] && [ -f "$revision_file" ]; then | |
| local fx_set_revision | |
| fx_set_revision="$(head -n 1 "$revision_file")" | |
| if [ "$fx_set_revision" = "$current_revision" ]; then | |
| should_rebuild=false | |
| fi | |
| fi | |
| if $should_rebuild; then | |
| # Build in a temporary directory where we can arrange the module. | |
| # | |
| # Avoid "TMPDIR" since Go looks at that environment variable. | |
| BUILD_DIR=$(mktemp -d) | |
| trap 'rm -rf $BUILD_DIR' EXIT | |
| pushd "$BUILD_DIR" >/dev/null | |
| for target in go.{mod,sum} vendor; do | |
| ln -s "$FUCHSIA_DIR"/third_party/golibs/"${target}" . | |
| done | |
| # fx-set's only local imports (direct and transitive) are from //tools. We | |
| # can symlink more top-level directories as necessary if fx-set ever needs | |
| # to import their code. | |
| ln -s "$FUCHSIA_DIR"/tools . | |
| # - GOPROXY=off enforces that we only use vendored dependencies and don't | |
| # download anything. | |
| # - GO111MODULE=on ensures that we use modules for the build even if the | |
| # user has GO111MODULE=off in their local environment. | |
| # - -buildvcs=false disables inclusion of version control information in the | |
| # resulting binary. It's not needed, and including it requires `go build` | |
| # to query for git status, which takes time and can trigger git garbage | |
| # collection that messes with ninja build convergence. | |
| # - GOCACHE="${FX_CACHE_DIR}/gocache" makes sure this script won't write | |
| # outside of Fuchsia dir when bootstrapping. | |
| if ! CGO_ENABLED=0 GOPROXY=off GO111MODULE=on GOCACHE="${FX_CACHE_DIR}/gocache" fx-command-run go build -buildvcs=false -o "$exe_path" ./tools/build/fx-set/cmd; then | |
| if ! $dev; then # If running in dev mode, compilation failures are expected. | |
| fx-error "Failed to build fx set." | |
| fi | |
| return 1 | |
| fi | |
| popd >/dev/null | |
| # Record the current HEAD *after* building fx-set so that we always try | |
| # to rebuild on subsequent attempts if compilation fails the first time. | |
| echo "$current_revision" >"$revision_file" | |
| fi | |
| # If --dir is used, FUCHSIA_BUILD_DIR will not be empty, and _FX_BUILD_DIR | |
| # must be set to its value before calling $exe_path, see https://fxbug.dev/413713238 | |
| if [[ -n "$FUCHSIA_BUILD_DIR" ]]; then | |
| export _FX_BUILD_DIR="${FUCHSIA_BUILD_DIR}" | |
| fi | |
| "$exe_path" "$@" | |
| status="$?" | |
| if [[ "$status" -eq 0 && "$enable_resultstore" = true ]]; then | |
| # Re-source vars.sh to update FUCHSIA_BUILD_DIR to the newly set up build dir. | |
| source "${FUCHSIA_DIR}/tools/devshell/lib/vars.sh" | |
| if [[ -n "${FUCHSIA_BUILD_DIR}" && -d "${FUCHSIA_BUILD_DIR}" ]]; then | |
| local -r local_config="${FUCHSIA_BUILD_DIR}/.resultstore" | |
| fx-resultstore-write-config "${local_config}" "all" | |
| echo "ResultStore uploading has been enabled locally for this build directory: ${FUCHSIA_BUILD_DIR}" | |
| fi | |
| fi | |
| # Check for RBE requirements if enabled. | |
| # Could be interactive if credentials need to be refreshed. | |
| fx-command-run rbe preflight | |
| return "$status" | |
| } | |
| main "$@" |