• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2#
3# Copyright 2023 The Bazel Authors. All rights reserved.
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
17# --- begin runfiles.bash initialization v2 ---
18# Copy-pasted from the Bazel Bash runfiles library v2.
19set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
20source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
21  source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
22  source "$0.runfiles/$f" 2>/dev/null || \
23  source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
24  source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
25  { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
26# --- end runfiles.bash initialization v2 ---
27
28source "$(rlocation rules_android/test/bashunit/unittest.bash)" || \
29  (echo >&2 "Failed to locate bashunit.sh" && exit 1)
30
31function set_up() {
32  # Clean out the repository.
33  rm -rf *
34  touch WORKSPACE
35
36  # Clean out the test android SDK if any
37  rm -rf "${TEST_TMPDIR}/android_sdk"
38
39  # Make sure the rules exist and seed the WORKSPACE.
40  rm -rf "${TEST_TMPDIR}/android_sdk_repository_src"
41  set_up_rules
42}
43
44function set_up_rules() {
45  local android_revision_rule="$(rlocation rules_android/rules/android_revision.bzl)"
46
47  local repo_rule="$(rlocation rules_android/rules/android_sdk_repository/rule.bzl)"
48  local repo_rule_dir="$(dirname "${repo_rule}")"
49  local dest_dir="${TEST_TMPDIR}/android_sdk_repository_src"
50  mkdir -p "${dest_dir}/rules/android_sdk_repository"
51  cp -r "${repo_rule_dir}"/* "${dest_dir}/rules/android_sdk_repository"
52  cat > "${dest_dir}/WORKSPACE" <<EOF
53workspace(name = "android_sdk_repository_src")
54EOF
55  cat > "${dest_dir}/rules/BUILD" <<EOF
56exports_files(["*.bzl"])
57EOF
58  cp "${android_revision_rule}" "${dest_dir}/rules/"
59  cat > "${dest_dir}/rules/android_sdk_repository/BUILD" <<EOF
60exports_files(["*.bzl"])
61EOF
62
63  cat >> WORKSPACE <<EOF
64local_repository(
65    name = "android_sdk_repository_src",
66    path = "${dest_dir}",
67)
68load("@android_sdk_repository_src//rules/android_sdk_repository:rule.bzl", "android_sdk_repository")
69EOF
70}
71
72function create_android_sdk() {
73  # Create a fake Android SDK that will be available for the repository rule.
74  local location="${TEST_TMPDIR}/android_sdk"
75  mkdir -p "${location}"
76
77  mkdir "${location}/platform-tools"
78  touch "${location}/platform-tools/adb"
79
80  echo "${location}"
81}
82
83function add_platforms() {
84  local sdk_path="${1}"
85  shift
86
87  # Add all requested API levels
88  for level in "$@"; do
89    local dir="${sdk_path}/platforms/android-${level}"
90    mkdir -p "${dir}"
91    touch "${dir}/android.jar"
92    touch "${dir}/framework.aidl"
93
94    local system_image_dir="${sdk_path}/system-images/android-${level}"
95    mkdir -p "${system_image_dir}/default/arm64-v8a"
96    mkdir -p "${system_image_dir}/default/x86_64"
97  done
98}
99
100function add_build_tools() {
101  local sdk_path="${1}"
102  shift
103
104  # Add all requested tools
105  for version in "$@"; do
106    local dir="${sdk_path}/build-tools/${version}"
107    mkdir -p "${dir}/lib"
108    touch "${dir}/aapt"
109    touch "${dir}/aidl"
110    touch "${dir}/lib/apksigner.jar"
111    touch "${dir}/lib/d8.jar"
112    touch "${dir}/lib/dx.jar"
113    touch "${dir}/mainDexClasses.rules"
114    touch "${dir}/zipalign"
115  done
116}
117
118function create_android_sdk_basic() {
119  local sdk_path="$(create_android_sdk)"
120  add_platforms "${sdk_path}" 31
121  add_build_tools "${sdk_path}" 30.0.3
122  echo "${sdk_path}"
123}
124
125function create_verify() {
126  mkdir verify
127  cat > verify/BUILD <<EOF
128genrule(
129    name = "check_sdk",
130    outs = ["check_sdk.log"],
131    cmd = select({
132        "@androidsdk//:has_androidsdk": "echo sdk present > \$@",
133        "//conditions:default": "echo sdk missing > \$@",
134    }),
135)
136EOF
137
138  "${BIT_BAZEL_BINARY}" build //verify:check_sdk >& $TEST_log || fail "Expected success"
139  cat bazel-bin/verify/check_sdk.log >$TEST_log
140}
141
142function verify_no_android_sdk() {
143  create_verify
144  expect_log "sdk missing"
145}
146
147function verify_android_sdk() {
148  create_verify
149  expect_log "sdk present"
150  "${BIT_BAZEL_BINARY}" query @androidsdk//:files >& $TEST_log || fail "Expected to exist"
151}
152
153function write_platforms() {
154  mkdir -p platforms
155  cat > platforms/BUILD <<EOF
156platform(
157    name = "arm64-v8a",
158    constraint_values = [
159        "@platforms//os:android",
160        "@platforms//cpu:arm64",
161    ],
162)
163EOF
164}
165
166function write_android_sdk_provider() {
167  mkdir -p sdk_check
168  cat > sdk_check/check.bzl <<EOF
169def _find_api_level(android_jar):
170    # expected format: external/androidsdk/platforms/android-LEVEL/android.jar
171    if not android_jar.startswith("external/androidsdk/platforms/android-"):
172        return "unknown"
173    if not android_jar.endswith("/android.jar"):
174        return "unknown"
175    level = android_jar.removeprefix("external/androidsdk/platforms/android-")
176    level = level.removesuffix("/android.jar")
177    return level
178def _show_sdk_info_impl(ctx):
179    print("SDK check results:")
180    provider = ctx.attr._android_sdk[AndroidSdkInfo]
181    print("build_tools_version: %s" % provider.build_tools_version)
182    print("api_level: %s" % _find_api_level(provider.android_jar.path))
183show_sdk_info = rule(
184    implementation = _show_sdk_info_impl,
185    attrs = {
186        "_android_sdk": attr.label(default = "@androidsdk//:sdk"),
187    },
188)
189EOF
190}
191
192function write_android_sdk_provider_platforms() {
193  mkdir -p sdk_check
194  cat > sdk_check/check.bzl <<EOF
195def _find_api_level(android_jar):
196    # expected format: external/androidsdk/platforms/android-LEVEL/android.jar
197    if not android_jar.startswith("external/androidsdk/platforms/android-"):
198        return "unknown"
199    if not android_jar.endswith("/android.jar"):
200        return "unknown"
201    level = android_jar.removeprefix("external/androidsdk/platforms/android-")
202    level = level.removesuffix("/android.jar")
203    return level
204def _show_sdk_info_impl(ctx):
205    print("SDK check results:")
206    toolchain = ctx.toolchains["@bazel_tools//tools/android:sdk_toolchain_type"]
207    if not toolchain:
208        print("No SDK found via toolchain")
209        return
210    provider = toolchain.android_sdk_info
211    print("build_tools_version: %s" % provider.build_tools_version)
212    print("api_level: %s" % _find_api_level(provider.android_jar.path))
213show_sdk_info = rule(
214    implementation = _show_sdk_info_impl,
215    toolchains = [
216        config_common.toolchain_type(
217            "@bazel_tools//tools/android:sdk_toolchain_type",
218            mandatory = False,
219        ),
220    ],
221)
222EOF
223}
224
225function check_android_sdk_provider() {
226  local extra_args=(
227    # macOS bash doesn't deal well with empty arrays, so make sure this has
228    # contents.
229    "--experimental_google_legacy_api"
230    "$@"
231  )
232
233  if [[ ${ENABLE_PLATFORMS:-false} == "true" ]]; then
234    write_platforms
235    write_android_sdk_provider_platforms
236    extra_args+=(
237      "--incompatible_enable_android_toolchain_resolution"
238      "--platforms=//platforms:arm64-v8a"
239    )
240  else
241    write_android_sdk_provider
242  fi
243
244  cat > sdk_check/BUILD <<EOF
245load(":check.bzl", "show_sdk_info")
246show_sdk_info(
247    name = "check",
248)
249EOF
250
251  "${BIT_BAZEL_BINARY}" \
252    build \
253    "${extra_args[@]}" \
254    -- \
255    //sdk_check:check >& $TEST_log || fail "Expected success"
256  expect_log "SDK check results"
257}
258