1#!/bin/bash 2 3# Copyright (C) 2022 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17set -eo pipefail 18 19source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh 20require_top 21 22 23ABSOLUTE_OUT_DIR="$(getoutdir)" 24# Store all bazel-related metadata files in this subdir of OUT_DIR. 25BAZEL_METADATA_OUT="${ABSOLUTE_OUT_DIR}/bazel" 26mkdir -p "${BAZEL_METADATA_OUT}" 27 28case $(uname -s) in 29 Darwin) 30 ANDROID_BAZEL_PATH="${TOP}/prebuilts/bazel/darwin-x86_64/bazel" 31 ANDROID_BAZELRC_NAME="darwin.bazelrc" 32 ANDROID_BAZEL_JDK_PATH="${TOP}/prebuilts/jdk/jdk21/darwin-x86" 33 34 # Lock down PATH in action execution environment, thereby removing 35 # Bazel's default /bin, /usr/bin, /usr/local/bin and ensuring 36 # hermeticity from the system. 37 # 38 # The new PATH components are: 39 # 40 # - prebuilts/build-tools/path: contains checked-in tools that can be 41 # used as executables in actions. 42 # 43 # - out/.path: a special directory created by path_interposer with 44 # config from ui/build/paths/config.go for allowlisting specific 45 # binaries not in prebuilts/build-tools/path, but on the host system. 46 # If one runs Bazel without soong_ui, then this directory wouldn't 47 # exist, making standalone Bazel execution's PATH variable stricter than 48 # Bazel execution within soong_ui. 49 RESTRICTED_PATH="${TOP}/prebuilts/build-tools/path/darwin-x86:${ABSOLUTE_OUT_DIR}/.path" 50 ;; 51 Linux) 52 ANDROID_BAZEL_PATH="${TOP}/prebuilts/bazel/linux-x86_64/bazel" 53 ANDROID_BAZELISK_PATH="${TOP}/prebuilts/bazel/linux-x86_64/dev_tools/bazelisk/bazelisk" 54 ANDROID_BAZELRC_NAME="linux.bazelrc" 55 ANDROID_BAZEL_JDK_PATH="${TOP}/prebuilts/jdk/jdk21/linux-x86" 56 RESTRICTED_PATH="${TOP}/prebuilts/build-tools/path/linux-x86:${ABSOLUTE_OUT_DIR}/.path" 57 ;; 58 *) 59 >&2 echo "Bazel is supported on Linux and Darwin only. Your OS is not supported for Bazel usage, based on 'uname -s': $(uname -s)" 60 exit 1 61 ;; 62esac 63 64function verify_soong_outputs_exist() { 65 local to_check="${ABSOLUTE_OUT_DIR}/.path" 66 local no_soong=0 67 if [[ ! -d "${to_check}" ]]; then 68 no_soong=1 69 fi 70 71 local bazel_configs=( 72 "bp2build" 73 "queryview" 74 ) 75 local valid_bazel_config=0 76 for c in "${bazel_configs[@]}" 77 do 78 if [[ -d "${ABSOLUTE_OUT_DIR}/soong/""${c}" ]]; then 79 valid_bazel_config=1 80 fi 81 done 82 83 if [[ "${no_soong}" -eq "1" || "${valid_bazel_config}" -eq "0" ]]; then 84 >&2 echo "Error: missing generated Bazel files. Have you run bp2build or queryview?" 85 >&2 echo "Run bp2build with the command: m bp2build" 86 >&2 echo "Run queryview with the command: m queryview" 87 >&2 echo "Alternatively, for non-queryview applications, invoke Bazel using 'b' with the command: source envsetup.sh; b query/build/test <targets>" 88 exit 1 89 fi 90} 91 92function create_bazelrc() { 93 cat > "${BAZEL_METADATA_OUT}/generated.bazelrc" <<EOF 94# This file is generated by build/bazel/bin/bazel. Do not edit manually. 95build --action_env=PATH=${RESTRICTED_PATH} 96 97# The --package_path option needs to be added to several different 98# bazel subcommands, because they don't inherit from each other, and 99# if we put it on "common", then it would break other commands like 100# shutdown that don't support --package_path. In addition, we have 101# to set at least one option on the "common" target so that bazel 102# won't complain that bp2build doesn't exist when using 103# --config=bp2build. We'll use --noannounce_rc for that, because 104# --noannounce_rc is the default. 105 106 107# Run bazel query from the workspace, without cd'ing into \$OUT_DIR/soong/queryview 108common:queryview --noannounce_rc 109build:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview 110fetch:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview 111mod:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview 112query:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview 113sync:queryview --package_path=${ABSOLUTE_OUT_DIR}/soong/queryview 114 115# Run bazel build from the workspace, without cd'ing into \$OUT_DIR/soong/workspace 116common:bp2build --noannounce_rc 117build:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace 118fetch:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace 119mod:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace 120query:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace 121sync:bp2build --package_path=${ABSOLUTE_OUT_DIR}/soong/workspace 122 123EOF 124} 125 126# Return 1 if STANDALONE_BAZEL is truthy 127function is_standalone_bazel() { 128 [[ ${STANDALONE_BAZEL} =~ ^(true|TRUE|1)$ ]] 129} 130 131case "x${ANDROID_BAZELRC_PATH}" in 132 x) 133 # Path not provided, use default. 134 if is_standalone_bazel; then 135 # Standalone bazel uses the empty /dev/null bazelrc 136 # This is necessary since some configs in common.bazelrc depend on soong_injection 137 ANDROID_BAZELRC_PATH=/dev/null 138 else 139 ANDROID_BAZELRC_PATH="${TOP}/build/bazel" 140 fi 141 ;; 142 x/*) 143 # Absolute path, take it as-is. 144 ANDROID_BAZELRC_PATH="${ANDROID_BAZELRC_PATH}" 145 ;; 146 x*) 147 # Relative path, consider it relative to TOP. 148 ANDROID_BAZELRC_PATH="${TOP}/${ANDROID_BAZELRC_PATH}" 149 ;; 150esac 151 152if [ -d "${ANDROID_BAZELRC_PATH}" ]; then 153 # If we're given a directory, find the correct bazelrc file there. 154 ANDROID_BAZELRC_PATH="${ANDROID_BAZELRC_PATH}/${ANDROID_BAZELRC_NAME}" 155fi 156 157ADDITIONAL_FLAGS=() 158 159if [[ -z ${USE_BAZEL_VERSION+x} ]]; then 160 if [ -n "$ANDROID_BAZEL_PATH" -a -f "$ANDROID_BAZEL_PATH" ]; then 161 export ANDROID_BAZEL_PATH 162 else 163 >&2 echo "Couldn't locate Bazel binary" 164 exit 1 165 fi 166else 167 echo -e "\033[1m\033[33mUSING BAZELISK:\033[0m Using Bazelisk because of env var: USE_BAZEL_VERSION=${USE_BAZEL_VERSION}" >&2 168 ANDROID_BAZEL_PATH=$ANDROID_BAZELISK_PATH 169 export ANDROID_BAZEL_PATH 170 # TODO(b/283971340): Pass BAZELISK_NOJDK=1 when this works with bazelisk. 171fi 172 173if [ "$ANDROID_BAZELRC_PATH" == "/dev/null" ] || [ -n "$ANDROID_BAZELRC_PATH" -a -f "$ANDROID_BAZELRC_PATH" ]; then 174 export ANDROID_BAZELRC_PATH 175else 176 >&2 echo "Couldn't locate bazelrc file for Bazel" 177 exit 1 178fi 179 180if [ -n "$ANDROID_BAZEL_JDK_PATH" -a -d "$ANDROID_BAZEL_JDK_PATH" ]; then 181 export ANDROID_BAZEL_JDK_PATH 182else 183 >&2 echo "Couldn't locate JDK to use for Bazel" 184 exit 1 185fi 186 187# In order to be able to load JNI libraries, this directory needs to exist 188mkdir -p "${BAZEL_METADATA_OUT}/javatmp" 189 190# Output a deps file. Soong will read these as dependencies for mixed builds 191MIXED_BUILDS_DOTD="${BAZEL_METADATA_OUT}/bazel.list" 192touch "${MIXED_BUILDS_DOTD}" 193echo $ANDROID_BAZEL_PATH > "${MIXED_BUILDS_DOTD}" 194echo $ANDROID_BAZELRC_PATH >> "${MIXED_BUILDS_DOTD}" 195echo $ANDROID_BAZEL_JDK_PATH >> "${MIXED_BUILDS_DOTD}" 196 197 198if is_standalone_bazel; then 199 # STANDALONE_BAZEL is set. 200 >&2 echo "WARNING: Using Bazel in standalone mode. This mode is not integrated with Soong and Make, and is not supported" 201 >&2 echo "for Android Platform builds. Use this mode at your own risk." 202 >&2 echo 203else 204 # Generate a bazelrc with dynamic content, like the absolute path to PATH variable values. 205 create_bazelrc 206 # Check that the Bazel synthetic workspace and other required inputs exist before handing over control to Bazel. 207 verify_soong_outputs_exist 208 ADDITIONAL_FLAGS+=("--bazelrc=${BAZEL_METADATA_OUT}/generated.bazelrc") 209 210 # These bazelrc files are only available when bp2build has been run. 211 # Standalone bazel and queryview don't run bp2build. 212 if [[ -f "${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/common.bazelrc" ]]; then 213 ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/common.bazelrc") 214 case $(uname -s) in 215 Darwin) 216 ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/darwin.bazelrc") 217 ;; 218 Linux) 219 ADDITIONAL_FLAGS+=("--bazelrc=${ABSOLUTE_OUT_DIR}/soong/soong_injection/product_config_platforms/linux.bazelrc") 220 ;; 221 *) 222 >&2 echo "Bazel is supported on Linux and Darwin only. Your OS is not supported for Bazel usage, based on 'uname -s': $(uname -s)" 223 exit 1 224 ;; 225 esac 226 fi 227fi 228 229# Change the PATH variable for the bazel invocation to include RESTRICTED_PATH. 230# This only affects the workspace_status_marker script environment and 231# the bazel run environment, and works around a bug for Bazelisk where Bazelisk 232# behaves differently if no PATH is present. 233BAZEL_PATH=$PATH:${RESTRICTED_PATH} 234 235# TODO(b/240354506): Re-enable hsperfdata file creation without causing SIGBUS errors 236PATH="${BAZEL_PATH}" JAVA_HOME="${ANDROID_BAZEL_JDK_PATH}" \ 237 "${ANDROID_BAZEL_PATH}" \ 238 --server_javabase="${ANDROID_BAZEL_JDK_PATH}" \ 239 --output_user_root="${BAZEL_METADATA_OUT}/output_user_root" \ 240 --host_jvm_args=-Djava.io.tmpdir="${BAZEL_METADATA_OUT}/javatmp" \ 241 --nohome_rc --nosystem_rc \ 242 --bazelrc="${ANDROID_BAZELRC_PATH}" \ 243 "${ADDITIONAL_FLAGS[@]}" \ 244 "$@" 245