blob: ec15298b06250d1b688b2cd604881c985bf0ccf4 [file]
# Copyright 2022 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.
"""
Defines the Android Split configuration transition for properly handling native
dependencies
The intended order of checks is:
- When `--incompatible_enable_android_toolchain_resolution` is set:
- `--android_platforms`
- Split using the values of this flag as the target platform
- If this is unset, use the first value from `--platforms`.
- If this isn't a valid Android platform, an error will be thrown
during the build.
- Fall back to legacy flag logic:
- `--fat_apk_cpus`
- Split using the values of this flag as `--cpu`
- If this is unset, fall though.
- `--android_cpu`
- Don't split, just use the value of this flag as `--cpu`
- This will not update the output path to include "-android".
- If this is unset, fall though.
- Default
- This will not update the output path to include "-android".
- Don't split, using the same previously set `--cpu` value.
"""
load(":utils.bzl", "utils")
def _add_cls_prefix(name):
return "//command_line_option:" + name
# get command line setting from flag name
def _get_cls(settings, name, default = None):
return settings.get(_add_cls_prefix(name), default)
def _android_split_transition_impl(settings, __):
if _get_cls(settings, "incompatible_enable_android_toolchain_resolution"):
# Always use `--android_platforms` when toolchain resolution is enabled.
platforms_to_split = _get_cls(settings, "android_platforms")
if not platforms_to_split:
# If `--android_platforms` is unset, instead use only the first
# value from `--platforms`.
target_platform = utils.only(_get_cls(settings, "platforms"))
platforms_to_split = [target_platform]
return _handle_android_platforms(settings, platforms_to_split)
# Fall back to the legacy flags.
if _get_cls(settings, "fat_apk_cpu"):
return _handle_fat_apk_cpus(settings)
if (_get_cls(settings, "android_cpu") and
_get_cls(settings, "android_crosstool_top") and
_get_cls(settings, "android_crosstool_top") != _get_cls(settings, "crosstool_top")):
return _handle_android_cpu(settings)
return _handle_default_split(settings, _get_cls(settings, "cpu"))
def _non_split_cpus(new_split_options, name, settings):
if not _get_cls(settings, "fat_apk_hwasan") or not name.contains("arm64-v8a"):
return
# A HWASAN build is different from a regular one in these ways:
# - The native library install directory gets a "-hwasan" suffix
# - Some compiler/linker command line options are different (defined in
# the Android C++ toolchain)
# - The name of the output directory is changed so that HWASAN and
# non-HWASAN artifacts do not conflict
new_settings = dict(settings)
new_settings.update({
_add_cls_prefix("cc_output_directory_tag"): "hwasan",
_add_cls_prefix("android hwasan"): True,
})
new_split_options[name + "-hwasan"] = new_settings
def _handle_android_platforms(settings, platforms_to_split):
"""
Splits the configuration based on the values of --android_platforms.
Each split will set the --platforms flag to one value from
--android_platforms, as well as clean up a few other flags around native
CC builds.
"""
result = dict()
for platform in platforms_to_split:
name = platform.name
split_options = dict(settings)
# Disable fat APKs for the child configurations.
split_options[_add_cls_prefix("fat_apk_cpu")] = []
split_options[_add_cls_prefix("android_platforms")] = []
# The cpu flag will be set by platform mapping if a mapping exists.
split_options[_add_cls_prefix("platforms")] = [platform]
_cc_flags_from_android(settings, split_options)
result[name] = split_options
_non_split_cpus(result, name, settings)
return result
def _handle_default_split(settings, cpu):
""" Returns a single-split transition that uses the `--cpu`
This does not change any flags.
"""
result = dict()
result[cpu] = dict(settings)
_non_split_cpus(result, cpu, settings)
return result
def _handle_android_cpu(settings):
""" Returns a transition that sets `--cpu` to the value of `--android_cpu`
This also sets other C++ flags based on the corresponding Android flags.
"""
android_cpu = settings[_add_cls_prefix("android_cpu")]
split_options = dict(settings)
split_options[_add_cls_prefix("cpu")] = android_cpu
_cc_flags_from_android(settings, split_options)
# Ensure platforms aren't set so that platform mapping can take place.
split_options[_add_cls_prefix("platforms")] = []
# Because configuration is based on cpu flags we need to disable C++ toolchain resolution
split_options[_add_cls_prefix("incompatible_enable_cc_toolchain_resolution")] = False
return _handle_default_split(split_options, android_cpu)
def _handle_fat_apk_cpus(settings):
""" Returns a multi-split transition that sets `--cpu` with the values of `--fat_apk_cpu`
Also sets other C++ flags based on the corresponding Android flags.
"""
result = dict()
for cpu in sorted(_get_cls(settings, "fat_apk_cpu")):
split_options = dict(settings)
# Disable fat APKs for the child configurations.
split_options[_add_cls_prefix("fat_apk_cpu")] = []
split_options[_add_cls_prefix("android_platforms")] = []
# Set the cpu & android_cpu.
# TODO(bazel-team): --android_cpu doesn't follow --cpu right now; it should.
split_options[_add_cls_prefix("android_cpu")] = cpu
split_options[_add_cls_prefix("cpu")] = cpu
_cc_flags_from_android(settings, split_options)
# Ensure platforms aren't set so that platform mapping can take place.
split_options[_add_cls_prefix("platforms")] = []
# Because configuration is based on cpu flags we need to disable C++ toolchain resolution
split_options[_add_cls_prefix("incompatible_enable_cc_toolchain_resolution")] = False
result[cpu] = split_options
_non_split_cpus(result, cpu, split_options)
return result
def _cc_flags_from_android(settings, new_settings):
new_settings[_add_cls_prefix("compiler")] = _get_cls(settings, "android_compiler")
new_settings[_add_cls_prefix("grte_top")] = _get_cls(settings, "android_grte_top")
new_settings[_add_cls_prefix("dynamic_mode")] = _get_cls(settings, "android_dynamic_mode")
android_crosstool_top = _get_cls(settings, "android_crosstool_top")
if android_crosstool_top:
new_settings[_add_cls_prefix("crosstool_top")] = android_crosstool_top
new_settings[_add_cls_prefix("Android configuration distinguisher")] = "android"
android_split_transition = transition(
implementation = _android_split_transition_impl,
inputs = [
"//command_line_option:Android configuration distinguisher",
"//command_line_option:android hwasan",
"//command_line_option:cc_output_directory_tag",
"//command_line_option:android_compiler",
"//command_line_option:android_cpu",
"//command_line_option:android_crosstool_top",
"//command_line_option:android_dynamic_mode",
"//command_line_option:android_grte_top",
"//command_line_option:android_platforms",
"//command_line_option:compiler",
"//command_line_option:cpu",
"//command_line_option:crosstool_top",
"//command_line_option:dynamic_mode",
"//command_line_option:grte_top",
"//command_line_option:fat_apk_cpu",
"//command_line_option:fat_apk_hwasan",
"//command_line_option:incompatible_enable_android_toolchain_resolution",
"//command_line_option:incompatible_enable_cc_toolchain_resolution",
"//command_line_option:platforms",
],
outputs = [
"//command_line_option:Android configuration distinguisher",
"//command_line_option:android hwasan",
"//command_line_option:cc_output_directory_tag",
"//command_line_option:android_compiler",
"//command_line_option:android_cpu",
"//command_line_option:android_crosstool_top",
"//command_line_option:android_dynamic_mode",
"//command_line_option:android_grte_top",
"//command_line_option:android_platforms",
"//command_line_option:compiler",
"//command_line_option:cpu",
"//command_line_option:crosstool_top",
"//command_line_option:dynamic_mode",
"//command_line_option:grte_top",
"//command_line_option:fat_apk_cpu",
"//command_line_option:fat_apk_hwasan",
"//command_line_option:incompatible_enable_android_toolchain_resolution",
"//command_line_option:incompatible_enable_cc_toolchain_resolution",
"//command_line_option:platforms",
],
)