aboutsummaryrefslogtreecommitdiff
path: root/bin/bazel
blob: 9121b731ee0841189c6e37b7034d613f98360b62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/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/jdk11/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/jdk11/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[@]}" \
  "$@"