blob: 613227e9c78158184bc53c20f64c0caa2fc398ba [file] [log] [blame]
#!/bin/bash
# Copyright 2017 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
### Run Ninja to build Fuchsia
## usage: fx build [--log FILENAME] [-SWITCH...] | TARGET ...]
##
## This runs Ninja after performing a few correctness checks for the Fuchsia build.
##
## optional arguments:
## --log LOGFILE Print debug information to LOGFILE. Please attach
## the resulting file when reporting bugs.
## --fint-params-path PATH Path to a fint params file used by an infra
## builder. This is useful for reproducing the exact
## set of targets built by the infrastructure.
##
## Other arguments are passed through to Ninja.
## Run `fx build -h` to see Ninja argument details.
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $?
fx-config-read
function main {
local switches=() fuchsia_targets=()
local log_file is_logging fint_params_path
is_logging=false
while [[ $# -gt 0 ]]; do
case "$1" in
--log)
if [[ $# -lt 2 ]]; then
fx-command-help
return 1
fi
log_file="$2"
if [[ -f "${log_file}" ]]; then
fx-error "File \"${log_file}\" exists."
return 1
fi
# if ! touch "${log_file}"; then
# fx-error "Cannot create logfile \"${log_file}\""
# return 1
# fi
is_logging=true
shift
;;
--fint-params-path)
if [[ $# -lt 2 ]]; then
fx-command-help
return 1
fi
fint_params_path="$2"
shift
;;
# These Ninja switches take an argument.
-[Cfjkldtw])
switches+=("$1" "$2")
shift
;;
-*)
switches+=("$1")
;;
*)
fuchsia_targets+=("$1")
;;
esac
shift
done
if [ -n "${fint_params_path}" ]; then
if [ ${#switches[@]} -gt 0 ]; then
fx-error "It's invalid to specify extra Ninja flags along with --fint-params-path."
exit 1
elif [ ${#fuchsia_targets[@]} -gt 0 ]; then
fx-error "It's invalid to specify targets along with --fint-params-path."
exit 1
fi
fi
if [[ "${is_logging}" = true ]]; then
# log file header with relevant environment information
{
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
echo "Build initiated at ${TIMESTAMP}"
echo
echo "------ GIT QUICK INFO ------"
echo "$ git status"
git --no-optional-locks --git-dir="${FUCHSIA_DIR}/.git" status
echo
echo "$ git rev-parse JIRI_HEAD"
git --no-optional-locks --git-dir="${FUCHSIA_DIR}/.git" rev-parse JIRI_HEAD
echo
echo "------ CONTENTS OF args.gn ------"
echo "$ cat ${FUCHSIA_BUILD_DIR}/args.gn"
echo
cat "${FUCHSIA_BUILD_DIR}/args.gn"
echo
} >> "${log_file}" 2>&1
# tee stdout and stderr to log_file
exec > >(tee -a "${log_file}") 2>&1
fi
# A change to any of these might mean things are now done differently enough
# that ninja's automatic re-gen rule might not be triggered or might not work
# properly if it is triggered. So preemptively force a re-gen if that seems
# like a plausible possibility.
local -r landmines=("$PREBUILT_GN"
"$FUCHSIA_DIR/tools/devshell/build"
"$FUCHSIA_DIR/tools/devshell/lib/vars.sh"
)
local mine
for mine in "${landmines[@]}"; do
if [[ "$mine" -nt "${FUCHSIA_BUILD_DIR}/build.ninja" ]]; then
if [[ "${is_logging}" = true ]]; then
echo -e "\\n------ RUNNING gn gen ------"
fi
echo >&2 "Re-running gn gen first ($mine changed)"
fx-gen || return
break
fi
done
if [[ ! -d "$FUCHSIA_BUILD_DIR" ]]; then
if [[ "${is_logging}" = true ]]; then
echo -e "\\n------ RUNNING gn gen ------"
fi
echo >&2 "Re-running gn gen first (missing $FUCHSIA_BUILD_DIR)"
fx-gen || return
else
# We have a build directory, execute force clean checker, usually a no-op
"$FUCHSIA_DIR/scripts/fuchsia-vendored-python3.8" \
"$FUCHSIA_DIR/build/force_clean/force_clean_if_needed.py" \
--gn-bin "$PREBUILT_GN" \
--checkout-dir "$FUCHSIA_DIR" \
--build-dir "$FUCHSIA_BUILD_DIR"
fi
local status
if [[ "${is_logging}" = true ]]; then
local tool="ninja"
if [ -n "${fint_params_path}" ]; then
tool="fint build"
fi
echo -e "\\n------ RUNNING ${tool} ------"
fi
if [ -n "${fint_params_path}" ]; then
readonly fint="${FX_CACHE_DIR}/fint"
"$FUCHSIA_DIR/tools/integration/bootstrap.sh" -o "$fint" || exit $?
# It's not ideal that we resort to constructing the textproto file as a
# string, but it's easier than writing a Go tool solely for the purpose of
# constructing a protobuf with a couple top-level string fields set.
local rbe_wrapper=()
if fx-rbe-enabled; then rbe_wrapper=("${RBE_WRAPPER[@]}"); fi
"${rbe_wrapper[@]}" "$fint" -log-level=error build -static="${fint_params_path}" -context=<(echo "
checkout_dir: \"${FUCHSIA_DIR}\"
build_dir: \"${FUCHSIA_BUILD_DIR}\"
")
else
(fx-run-ninja "${is_logging}" "$PREBUILT_NINJA" -C "${FUCHSIA_BUILD_DIR}" \
"${switches[@]}" "${fuchsia_targets[@]}")
fi
status=$?
if [[ "${status}" -ne 0 ]]; then
goma-check
fi
exit-with-message
}
function goma-check {
if grep -q "^ *use_goma = true" "${FUCHSIA_BUILD_DIR}/args.gn"; then
if ! fx-command-run goma_ctl status >/dev/null 2>&1; then
fx-error "Goma is enabled but not started. Please run 'fx goma' first."
fi
fi
}
function exit-with-message {
if [[ "${is_logging}" = true ]]; then
fx-warn "Debug log saved to ${log_file}. Please attach this file when reporting a bug"
elif [[ "${status}" -ne 0 ]]; then
echo >&2 "Hint: run \`fx build\` with the option \`--log LOGFILE\` to generate a debug log if you are reporting a bug."
fi
exit "${status}"
}
main "$@"