blob: f58bf6eadeb3104d419dece51d631effa8aa6a09 [file] [log] [blame]
#!/bin/bash
# Copyright (C) 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -eo pipefail
source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
require_top
ABSOLUTE_OUT_DIR="$(getoutdir)"
# Store all bazel-related metadata files in this subdir of OUT_DIR.
BAZEL_METADATA_OUT="${ABSOLUTE_OUT_DIR}/bazel"
mkdir -p "${BAZEL_METADATA_OUT}"
case $(uname -s) in
Darwin)
ANDROID_BAZEL_PATH="${TOP}/prebuilts/bazel/darwin-x86_64/bazel"
ANDROID_BAZELRC_NAME="darwin.bazelrc"
ANDROID_BAZEL_JDK_PATH="${TOP}/prebuilts/jdk/jdk17/darwin-x86"
# Lock down PATH in action execution environment, thereby removing
# Bazel's default /bin, /usr/bin, /usr/local/bin and ensuring
# hermeticity from the system.
#
# The new PATH components are:
#
# - prebuilts/build-tools/path: contains checked-in tools that can be
# used as executables in actions.
#
# - out/.path: a special directory created by path_interposer with
# config from ui/build/paths/config.go for allowlisting specific
# binaries not in prebuilts/build-tools/path, but on the host system.
# If one runs Bazel without soong_ui, then this directory wouldn't
# exist, making standalone Bazel execution's PATH variable stricter than
# Bazel execution within soong_ui.
RESTRICTED_PATH="${TOP}/prebuilts/build-tools/path/darwin-x86:${ABSOLUTE_OUT_DIR}/.path"
;;
Linux)
ANDROID_BAZEL_PATH="${TOP}/prebuilts/bazel/linux-x86_64/bazel"
ANDROID_BAZELISK_PATH="${TOP}/prebuilts/bazel/linux-x86_64/dev_tools/bazelisk/bazelisk"
ANDROID_BAZELRC_NAME="linux.bazelrc"
ANDROID_BAZEL_JDK_PATH="${TOP}/prebuilts/jdk/jdk17/linux-x86"
RESTRICTED_PATH="${TOP}/prebuilts/build-tools/path/linux-x86:${ABSOLUTE_OUT_DIR}/.path"
;;
*)
>&2 echo "Bazel is supported on Linux and Darwin only. Your OS is not supported for Bazel usage, based on 'uname -s': $(uname -s)"
exit 1
;;
esac
function verify_soong_outputs_exist() {
local to_check="${ABSOLUTE_OUT_DIR}/.path"
local no_soong=0
if [[ ! -d "${to_check}" ]]; then
no_soong=1
fi
local bazel_configs=(
"bp2build"
"queryview"
)
local valid_bazel_config=0
for c in "${bazel_configs[@]}"
do
if [[ -d "${ABSOLUTE_OUT_DIR}/soong/""${c}" ]]; then
valid_bazel_config=1
fi
done
if [[ "${no_soong}" -eq "1" || "${valid_bazel_config}" -eq "0" ]]; then
>&2 echo "Error: missing generated Bazel files. Have you run bp2build or queryview?"
>&2 echo "Run bp2build with the command: m bp2build"
>&2 echo "Run queryview with the command: m queryview"
>&2 echo "Alternatively, for non-queryview applications, invoke Bazel using 'b' with the command: source envsetup.sh; b query/build/test <targets>"
exit 1
fi
}
function create_bazelrc() {
cat > "${BAZEL_METADATA_OUT}/generated.bazelrc" <<EOF
# This file is generated by build/bazel/bin/bazel. Do not edit manually.
build --action_env=PATH=${RESTRICTED_PATH}
# The --package_path option needs to be added to several different
# bazel subcommands, because they don't inherit from each other, and
# if we put it on "common", then it would break other commands like
# shutdown that don't support --package_path. In addition, we have
# to set at least one option on the "common" target so that bazel
# won't complain that bp2build doesn't exist when using
# --config=bp2build. We'll use --noannounce_rc for that, because
# --noannounce_rc is the default.
# Run bazel query from the workspace, without cd'ing into \$OUT_DIR/soong/queryview
common:queryview --noannounce_rc
build:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview
fetch:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview
mod:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview
query:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview
sync:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview
# Run bazel build from the workspace, without cd'ing into \$OUT_DIR/soong/workspace
common:bp2build --noannounce_rc
build:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace
fetch:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace
mod:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace
query:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace
sync:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace
EOF
}
# Return 1 if STANDALONE_BAZEL is truthy
function is_standalone_bazel() {
[[ ${STANDALONE_BAZEL} =~ ^(true|TRUE|1)$ ]]
}
case "x${ANDROID_BAZELRC_PATH}" in
x)
# Path not provided, use default.
if is_standalone_bazel; then
# Standalone bazel uses the empty /dev/null bazelrc
# This is necessary since some configs in common.bazelrc depend on soong_injection
ANDROID_BAZELRC_PATH=/dev/null
else
ANDROID_BAZELRC_PATH="${TOP}/build/bazel"
fi
;;
x/*)
# Absolute path, take it as-is.
ANDROID_BAZELRC_PATH="${ANDROID_BAZELRC_PATH}"
;;
x*)
# Relative path, consider it relative to TOP.
ANDROID_BAZELRC_PATH="${TOP}/${ANDROID_BAZELRC_PATH}"
;;
esac
if [ -d "${ANDROID_BAZELRC_PATH}" ]; then
# If we're given a directory, find the correct bazelrc file there.
ANDROID_BAZELRC_PATH="${ANDROID_BAZELRC_PATH}/${ANDROID_BAZELRC_NAME}"
fi
ADDITIONAL_FLAGS=()
if [[ -z ${USE_BAZEL_VERSION+x} ]]; then
if [ -n "$ANDROID_BAZEL_PATH" -a -f "$ANDROID_BAZEL_PATH" ]; then
export ANDROID_BAZEL_PATH
else
>&2 echo "Couldn't locate Bazel binary"
exit 1
fi
else
echo -e "\033[1m\033[33mUSING BAZELISK:\033[0m Using Bazelisk because of env var: USE_BAZEL_VERSION=${USE_BAZEL_VERSION}" >&2
ANDROID_BAZEL_PATH=$ANDROID_BAZELISK_PATH
export ANDROID_BAZEL_PATH
# TODO(b/283971340): Pass BAZELISK_NOJDK=1 when this works with bazelisk.
fi
if [ "$ANDROID_BAZELRC_PATH" == "/dev/null" ] || [ -n "$ANDROID_BAZELRC_PATH" -a -f "$ANDROID_BAZELRC_PATH" ]; then
export ANDROID_BAZELRC_PATH
else
>&2 echo "Couldn't locate bazelrc file for Bazel"
exit 1
fi
if [ -n "$ANDROID_BAZEL_JDK_PATH" -a -d "$ANDROID_BAZEL_JDK_PATH" ]; then
export ANDROID_BAZEL_JDK_PATH
else
>&2 echo "Couldn't locate JDK to use for Bazel"
exit 1
fi
# In order to be able to load JNI libraries, this directory needs to exist
mkdir -p "${BAZEL_METADATA_OUT}/javatmp"
# Output a deps file. Soong will read these as dependencies for mixed builds
MIXED_BUILDS_DOTD="${BAZEL_METADATA_OUT}/bazel.list"
touch "${MIXED_BUILDS_DOTD}"
echo $ANDROID_BAZEL_PATH > "${MIXED_BUILDS_DOTD}"
echo $ANDROID_BAZELRC_PATH >> "${MIXED_BUILDS_DOTD}"
echo $ANDROID_BAZEL_JDK_PATH >> "${MIXED_BUILDS_DOTD}"
if is_standalone_bazel; then
# STANDALONE_BAZEL is set.
>&2 echo "WARNING: Using Bazel in standalone mode. This mode is not integrated with Soong and Make, and is not supported"
>&2 echo "for Android Platform builds. Use this mode at your own risk."
>&2 echo
else
# Generate a bazelrc with dynamic content, like the absolute path to PATH variable values.
create_bazelrc
# Check that the Bazel synthetic workspace and other required inputs exist before handing over control to Bazel.
verify_soong_outputs_exist
ADDITIONAL_FLAGS+=("--bazelrc=${BAZEL_METADATA_OUT}/generated.bazelrc")
# These bazelrc files are only available when bp2build has been run.
# Standalone bazel and queryview don't run bp2build.
if [[ -f "${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/common.bazelrc" ]]; then
ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/common.bazelrc")
case $(uname -s) in
Darwin)
ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/darwin.bazelrc")
;;
Linux)
ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/linux.bazelrc")
;;
*)
>&2 echo "Bazel is supported on Linux and Darwin only. Your OS is not supported for Bazel usage, based on 'uname -s': $(uname -s)"
exit 1
;;
esac
fi
fi
# Change the PATH variable for the bazel invocation to include RESTRICTED_PATH.
# This only affects the workspace_status_marker script environment and
# the bazel run environment, and works around a bug for Bazelisk where Bazelisk
# behaves differently if no PATH is present.
BAZEL_PATH=$PATH:${RESTRICTED_PATH}
# TODO(b/240354506): Re-enable hsperfdata file creation without causing SIGBUS errors
PATH="${BAZEL_PATH}" JAVA_HOME="${ANDROID_BAZEL_JDK_PATH}" \
"${ANDROID_BAZEL_PATH}" \
--server_javabase="${ANDROID_BAZEL_JDK_PATH}" \
--output_user_root="${BAZEL_METADATA_OUT}/output_user_root" \
--host_jvm_args=-Djava.io.tmpdir="${BAZEL_METADATA_OUT}/javatmp" \
--nohome_rc --nosystem_rc \
--bazelrc="${ANDROID_BAZELRC_PATH}" \
"${ADDITIONAL_FLAGS[@]}" \
"$@"