| """Template for the build file used in android_sdk_repository.""" | |
| # Copyright 2016 The Bazel Authors. All rights reserved. | |
| # | |
| # 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. | |
| load("@rules_java//java:defs.bzl", "java_binary", "java_import") | |
| def create_config_setting_rule(): | |
| """Create config_setting rule for windows. | |
| These represent the matching --host_cpu values. | |
| """ | |
| name = "windows" | |
| if not native.existing_rule(name): | |
| native.config_setting( | |
| name = name, | |
| values = {"host_cpu": "x64_" + name}, | |
| ) | |
| native.config_setting( | |
| name = "d8_standalone_dexer", | |
| values = {"define": "android_standalone_dexing_tool=d8_compat_dx"}, | |
| ) | |
| native.config_setting( | |
| name = "dx_standalone_dexer", | |
| values = {"define": "android_standalone_dexing_tool=dx_compat_dx"}, | |
| ) | |
| def create_android_sdk_rules( | |
| name, | |
| build_tools_version, | |
| build_tools_directory, | |
| api_levels, | |
| default_api_level): | |
| """Generate android_sdk rules for the API levels in the Android SDK. | |
| Args: | |
| name: string, the name of the repository being generated. | |
| build_tools_version: string, the version of Android's build tools to use. | |
| build_tools_directory: string, the directory name of the build tools in | |
| sdk's build-tools directory. | |
| api_levels: list of ints, the API levels from which to get android.jar | |
| et al. and create android_sdk rules. | |
| default_api_level: int, the API level to alias the default sdk to if | |
| --android_sdk is not specified on the command line. | |
| """ | |
| create_config_setting_rule() | |
| windows_only_files = [ | |
| "build-tools/%s/aapt.exe" % build_tools_directory, | |
| "build-tools/%s/aidl.exe" % build_tools_directory, | |
| "build-tools/%s/zipalign.exe" % build_tools_directory, | |
| "platform-tools/adb.exe", | |
| ] + native.glob(["build-tools/%s/aapt2.exe" % build_tools_directory]) | |
| linux_only_files = [ | |
| "build-tools/%s/aapt" % build_tools_directory, | |
| "build-tools/%s/aidl" % build_tools_directory, | |
| "build-tools/%s/zipalign" % build_tools_directory, | |
| "platform-tools/adb", | |
| ] + native.glob( | |
| ["extras", "build-tools/%s/aapt2" % build_tools_directory], | |
| exclude_directories = 0, | |
| ) | |
| # This filegroup is used to pass the minimal contents of the SDK to the | |
| # Android integration tests. Note that in order to work on Windows, we cannot | |
| # include directories and must keep the size small. | |
| native.filegroup( | |
| name = "files", | |
| srcs = [ | |
| "build-tools/%s/lib/apksigner.jar" % build_tools_directory, | |
| "build-tools/%s/lib/dx.jar" % build_tools_directory, | |
| "build-tools/%s/mainDexClasses.rules" % build_tools_directory, | |
| ] + [ | |
| "platforms/android-%d/%s" % (api_level, filename) | |
| for api_level in api_levels | |
| for filename in ["android.jar", "framework.aidl"] | |
| ] + select({ | |
| ":windows": windows_only_files, | |
| "//conditions:default": linux_only_files, | |
| }), | |
| ) | |
| for api_level in api_levels: | |
| if api_level >= 23: | |
| # Android 23 removed most of org.apache.http from android.jar and moved it | |
| # to a separate jar. | |
| java_import( | |
| name = "org_apache_http_legacy-%d" % api_level, | |
| jars = ["platforms/android-%d/optional/org.apache.http.legacy.jar" % api_level], | |
| ) | |
| if api_level >= 28: | |
| # Android 28 removed most of android.test from android.jar and moved it | |
| # to separate jars. | |
| java_import( | |
| name = "legacy_test-%d" % api_level, | |
| jars = [ | |
| "platforms/android-%d/optional/android.test.base.jar" % api_level, | |
| "platforms/android-%d/optional/android.test.mock.jar" % api_level, | |
| "platforms/android-%d/optional/android.test.runner.jar" % api_level, | |
| ], | |
| neverlink = 1, | |
| ) | |
| native.android_sdk( | |
| name = "sdk-%d" % api_level, | |
| build_tools_version = build_tools_version, | |
| proguard = "@bazel_tools//tools/jdk:proguard", | |
| aapt = select({ | |
| ":windows": "build-tools/%s/aapt.exe" % build_tools_directory, | |
| "//conditions:default": ":aapt_binary", | |
| }), | |
| aapt2 = select({ | |
| ":windows": "build-tools/%s/aapt2.exe" % build_tools_directory, | |
| "//conditions:default": ":aapt2_binary", | |
| }), | |
| dx = select({ | |
| "d8_standalone_dexer": ":d8_compat_dx", | |
| "dx_standalone_dexer": ":dx_binary", | |
| "//conditions:default": ":dx_binary", | |
| }), | |
| main_dex_list_creator = ":main_dex_list_creator", | |
| adb = select({ | |
| ":windows": "platform-tools/adb.exe", | |
| "//conditions:default": "platform-tools/adb", | |
| }), | |
| framework_aidl = "platforms/android-%d/framework.aidl" % api_level, | |
| aidl = select({ | |
| ":windows": "build-tools/%s/aidl.exe" % build_tools_directory, | |
| "//conditions:default": ":aidl_binary", | |
| }), | |
| android_jar = "platforms/android-%d/android.jar" % api_level, | |
| shrinked_android_jar = "platforms/android-%d/android.jar" % api_level, | |
| main_dex_classes = "build-tools/%s/mainDexClasses.rules" % build_tools_directory, | |
| apksigner = ":apksigner", | |
| zipalign = select({ | |
| ":windows": "build-tools/%s/zipalign.exe" % build_tools_directory, | |
| "//conditions:default": ":zipalign_binary", | |
| }), | |
| # See https://github.com/bazelbuild/bazel/issues/8757 | |
| tags = ["__ANDROID_RULES_MIGRATION__"], | |
| ) | |
| native.alias( | |
| name = "org_apache_http_legacy", | |
| actual = ":org_apache_http_legacy-%d" % default_api_level, | |
| ) | |
| native.alias( | |
| name = "sdk", | |
| actual = ":sdk-%d" % default_api_level, | |
| ) | |
| java_binary( | |
| name = "apksigner", | |
| main_class = "com.android.apksigner.ApkSignerTool", | |
| runtime_deps = ["build-tools/%s/lib/apksigner.jar" % build_tools_directory], | |
| ) | |
| native.filegroup( | |
| name = "build_tools_libs", | |
| srcs = native.glob([ | |
| "build-tools/%s/lib/**" % build_tools_directory, | |
| # Build tools version 24.0.0 added a lib64 folder. | |
| "build-tools/%s/lib64/**" % build_tools_directory, | |
| ]), | |
| ) | |
| for tool in ["aapt", "aapt2", "aidl", "zipalign"]: | |
| native.genrule( | |
| name = tool + "_runner", | |
| outs = [tool + "_runner.sh"], | |
| srcs = [], | |
| cmd = "\n".join([ | |
| "cat > $@ << 'EOF'", | |
| "#!/bin/bash", | |
| "set -eu", | |
| # The tools under build-tools/VERSION require the libraries under | |
| # build-tools/VERSION/lib, so we can't simply depend on them as a | |
| # file like we do with aapt. | |
| # On Windows however we can use these binaries directly because | |
| # there's no runfiles support so Bazel just creates a junction to | |
| # {SDK}/build-tools. | |
| "SDK=$${0}.runfiles/%s" % name, | |
| # If $${SDK} is not a directory, it means that this tool is running | |
| # from a runfiles directory, in the case of | |
| # android_instrumentation_test. Hence, use the androidsdk | |
| # that's already present in the runfiles of the current context. | |
| "if [[ ! -d $${SDK} ]] ; then", | |
| " SDK=$$(pwd)/../%s" % name, | |
| "fi", | |
| "exec $${SDK}/build-tools/%s/%s $$*" % (build_tools_directory, tool), | |
| "EOF\n", | |
| ]), | |
| ) | |
| native.sh_binary( | |
| name = tool + "_binary", | |
| srcs = [tool + "_runner.sh"], | |
| data = [ | |
| ":build_tools_libs", | |
| "build-tools/%s/%s" % (build_tools_directory, tool), | |
| ], | |
| ) | |
| native.sh_binary( | |
| name = "fail", | |
| srcs = select({ | |
| ":windows": [":generate_fail_cmd"], | |
| "//conditions:default": [":generate_fail_sh"], | |
| }), | |
| ) | |
| native.genrule( | |
| name = "generate_fail_sh", | |
| executable = 1, | |
| outs = ["fail.sh"], | |
| cmd = "echo -e '#!/bin/bash\\nexit 1' >> $@; chmod +x $@", | |
| ) | |
| native.genrule( | |
| name = "generate_fail_cmd", | |
| executable = 1, | |
| outs = ["fail.cmd"], | |
| cmd = "echo @exit /b 1 > $@", | |
| ) | |
| native.genrule( | |
| name = "main_dex_list_creator_source", | |
| srcs = [], | |
| outs = ["main_dex_list_creator.sh"], | |
| cmd = "\n".join([ | |
| "cat > $@ <<'EOF'", | |
| "#!/bin/bash", | |
| "", | |
| "MAIN_DEX_LIST=$$1", | |
| "STRIPPED_JAR=$$2", | |
| "JAR=$$3", | |
| "" + | |
| "JAVA_BINARY=$$0.runfiles/%s/main_dex_list_creator_java" % name, | |
| "$$JAVA_BINARY $$STRIPPED_JAR $$JAR > $$MAIN_DEX_LIST", | |
| "exit $$?", | |
| "", | |
| "EOF\n", | |
| ]), | |
| ) | |
| native.sh_binary( | |
| name = "main_dex_list_creator", | |
| srcs = ["main_dex_list_creator.sh"], | |
| data = [":main_dex_list_creator_java"], | |
| ) | |
| java_binary( | |
| name = "main_dex_list_creator_java", | |
| main_class = "com.android.multidex.ClassReferenceListBuilder", | |
| runtime_deps = [":dx_jar_import"], | |
| ) | |
| java_binary( | |
| name = "dx_binary", | |
| main_class = "com.android.dx.command.Main", | |
| runtime_deps = [":dx_jar_import"], | |
| ) | |
| java_import( | |
| name = "dx_jar_import", | |
| jars = ["build-tools/%s/lib/dx.jar" % build_tools_directory], | |
| ) | |
| java_binary( | |
| name = "d8_compat_dx", | |
| main_class = "com.android.tools.r8.compatdx.CompatDx", | |
| runtime_deps = [":d8_jar_import"], | |
| ) | |
| java_import( | |
| name = "d8_jar_import", | |
| jars = ["build-tools/%s/lib/d8.jar" % build_tools_directory], | |
| ) | |
| TAGDIR_TO_TAG_MAP = { | |
| "google_apis_playstore": "playstore", | |
| "google_apis": "google", | |
| "default": "android", | |
| "android-tv": "tv", | |
| "android-wear": "wear", | |
| } | |
| ARCHDIR_TO_ARCH_MAP = { | |
| "x86": "x86", | |
| "armeabi-v7a": "arm", | |
| } | |
| def create_system_images_filegroups(system_image_dirs): | |
| """Generate filegroups for the system images in the Android SDK. | |
| Args: | |
| system_image_dirs: list of strings, the directories containing system image | |
| files to be used to create android_device rules. | |
| """ | |
| # These images will need to be updated as Android releases new system images. | |
| # We are intentionally not adding future releases because there is no | |
| # guarantee that they will work out of the box. Supported system images should | |
| # be added here once they have been confirmed to work with the Bazel Android | |
| # testing infrastructure. | |
| system_images = [ | |
| (tag, str(api), arch) | |
| for tag in ["android", "google"] | |
| for api in [10] + list(range(15, 20)) + list(range(21, 30)) | |
| for arch in ("x86", "arm") | |
| ] + [ | |
| ("playstore", str(api), "x86") | |
| for api in list(range(24, 30)) | |
| ] | |
| tv_images = [ | |
| ("tv", str(api), "x86") | |
| for api in range(21, 30) | |
| ] + [ | |
| ("tv", "21", "arm"), | |
| ("tv", "23", "arm"), | |
| ] | |
| wear_images = [ | |
| ("wear", str(api), "x86") | |
| for api in [23, 25, 26, 28] | |
| ] + [ | |
| ("wear", str(api), "arm") | |
| for api in [23, 25] | |
| ] | |
| supported_system_images = system_images + tv_images + wear_images | |
| installed_system_images_dirs = {} | |
| for system_image_dir in system_image_dirs: | |
| apidir, tagdir, archdir = system_image_dir.split("/")[1:] | |
| if "-" not in apidir: | |
| continue | |
| api = apidir.split("-")[1] # "android-24" --> "24", "android-O" --> "O" | |
| if tagdir not in TAGDIR_TO_TAG_MAP: | |
| continue | |
| tag = TAGDIR_TO_TAG_MAP[tagdir] | |
| if archdir not in ARCHDIR_TO_ARCH_MAP: | |
| continue | |
| arch = ARCHDIR_TO_ARCH_MAP[archdir] | |
| if (tag, api, arch) in supported_system_images: | |
| name = "emulator_images_%s_%s_%s" % (tag, api, arch) | |
| installed_system_images_dirs[name] = system_image_dir | |
| else: | |
| # TODO(bazel-team): If the user has an unsupported system image installed, | |
| # should we print a warning? This includes all 64-bit system-images. | |
| pass | |
| for (tag, api, arch) in supported_system_images: | |
| name = "emulator_images_%s_%s_%s" % (tag, api, arch) | |
| if name in installed_system_images_dirs: | |
| system_image_dir = installed_system_images_dirs[name] | |
| # For supported system images that exist in /sdk/system-images/, we | |
| # create a filegroup with their contents. | |
| native.filegroup( | |
| name = name, | |
| srcs = native.glob([ | |
| "%s/**" % system_image_dir, | |
| ]), | |
| ) | |
| native.filegroup( | |
| name = "%s_qemu2_extra" % name, | |
| srcs = native.glob(["%s/kernel-ranchu" % system_image_dir]), | |
| ) | |
| else: | |
| # For supported system images that are not installed in the SDK, we | |
| # create a "poison pill" genrule to display a helpful error message to | |
| # a user who attempts to run a test against an android_device that | |
| # they don't have the system image for installed. | |
| native.genrule( | |
| name = name, | |
| outs = [ | |
| # Necessary so that the build doesn't fail in analysis because | |
| # android_device expects a file named source.properties. | |
| "poison_pill_for_%s/source.properties" % name, | |
| ], | |
| cmd = """echo \ | |
| This rule requires that the Android SDK used by Bazel has the \ | |
| following system image installed: %s. Please install this system \ | |
| image through the Android SDK Manager and try again. ; \ | |
| exit 1 | |
| """ % name, | |
| ) | |
| native.filegroup( | |
| name = "%s_qemu2_extra" % name, | |
| srcs = [], | |
| ) |