blob: be3f4e1ecc0acb61765b5ee5e83ee8fcd3e21c8b [file] [log] [blame]
"""Feature definitions for Android's C/C++ toolchain.
This top level list of features are available through the get_features function.
"""
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load(
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
"feature",
"feature_set",
"flag_group",
"flag_set",
"variable_with_value",
"with_feature_set",
)
load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesInfo")
load(
":cc_toolchain_constants.bzl",
_actions = "actions",
_arches = "arches",
_c_std_versions = "c_std_versions",
_cpp_std_versions = "cpp_std_versions",
_default_c_std_version = "default_c_std_version",
_default_c_std_version_no_gnu = "default_c_std_version_no_gnu",
_default_cpp_std_version = "default_cpp_std_version",
_default_cpp_std_version_no_gnu = "default_cpp_std_version_no_gnu",
_experimental_c_std_version = "experimental_c_std_version",
_experimental_c_std_version_no_gnu = "experimental_c_std_version_no_gnu",
_experimental_cpp_std_version = "experimental_cpp_std_version",
_experimental_cpp_std_version_no_gnu = "experimental_cpp_std_version_no_gnu",
_flags = "flags",
_generated_config_constants = "generated_config_constants",
_generated_sanitizer_constants = "generated_sanitizer_constants",
_oses = "oses",
)
load("//build/bazel/rules/common:api.bzl", "api")
load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions")
def is_os_device(os):
return os == _oses.Android
def is_os_bionic(os):
return os == _oses.Android or os == _oses.LinuxBionic
def _sdk_version_features_between(start, end):
return ["sdk_version_" + str(i) for i in range(start, end + 1)]
def _sdk_version_features_before(version):
return _sdk_version_features_between(1, version - 1)
def _get_sdk_version_features(os_is_device, target_arch):
if not os_is_device:
return []
default_sdk_version = "10000"
sdk_feature_prefix = "sdk_version_"
all_sdk_versions = [default_sdk_version]
for level in api.api_levels.values():
all_sdk_versions.append(str(level))
# Explicitly support internal branch state where the platform sdk version has
# finalized, but the sdk is still active, so it's represented by a 9000-ish
# value in api_levels.
platform_sdk_version = str(platform_versions.platform_sdk_version)
if platform_sdk_version not in all_sdk_versions:
all_sdk_versions.append(platform_sdk_version)
flag_prefix = "--target="
if target_arch == _arches.X86:
flag_prefix += "i686-linux-android"
elif target_arch == _arches.X86_64:
flag_prefix += "x86_64-linux-android"
elif target_arch == _arches.Arm:
flag_prefix += _generated_config_constants.ArmClangTriple
elif target_arch == _arches.Arm64:
flag_prefix += "aarch64-linux-android"
else:
fail("Unknown target arch %s" % (target_arch))
features = [feature(
name = "sdk_version_default",
enabled = True,
implies = [sdk_feature_prefix + default_sdk_version],
)]
features.extend([
feature(name = sdk_feature_prefix + sdk_version, provides = ["sdk_version"])
for sdk_version in all_sdk_versions
])
features.append(feature(
name = "sdk_version_flag",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile + _actions.link,
flag_groups = [
flag_group(
flags = [flag_prefix + sdk_version],
),
],
with_features = [
with_feature_set(
features = [sdk_feature_prefix + sdk_version],
),
],
)
for sdk_version in all_sdk_versions
],
))
return features
def _get_c_std_features():
features = []
features.append(feature(
# The default cpp_std feature. Remember to disable
# this feature if enabling another cpp_std feature.
name = "cpp_std_default",
enabled = True,
implies = [_default_cpp_std_version],
))
features.append(feature(
# The default c_std feature. Remember to disable
# this feature if enabling another cpp_std feature.
name = "c_std_default",
enabled = True,
implies = [_default_c_std_version],
))
features.append(feature(
name = "cpp_std_default_no_gnu",
implies = [_default_cpp_std_version_no_gnu],
))
features.append(feature(
name = "c_std_default_no_gnu",
implies = [_default_cpp_std_version_no_gnu],
))
features.append(feature(
name = "cpp_std_experimental",
implies = [_experimental_cpp_std_version],
))
features.append(feature(
name = "c_std_experimental",
implies = [_experimental_cpp_std_version],
))
features.append(feature(
name = "cpp_std_experimental_no_gnu",
implies = [_experimental_cpp_std_version_no_gnu],
))
features.append(feature(
name = "c_std_experimental_no_gnu",
implies = [_experimental_cpp_std_version_no_gnu],
))
features.extend([
feature(name = std_version, provides = ["cpp_std"])
for std_version in _cpp_std_versions
])
features.extend([
feature(name = std_version, provides = ["c_std"])
for std_version in _c_std_versions
])
features.append(feature(
name = "cpp_std_flag",
enabled = True,
# Create the -std flag group for each of the std versions,
# enabled with with_feature_set.
flag_sets = [
flag_set(
actions = [_actions.cpp_compile],
flag_groups = [
flag_group(
flags = ["-std=" + std_version],
),
],
with_features = [
with_feature_set(
features = [std_version],
),
],
)
for std_version in _cpp_std_versions
],
))
features.append(feature(
name = "c_std_flag",
enabled = True,
# Create the -std flag group for each of the std versions,
# enabled with with_feature_set.
flag_sets = [
flag_set(
actions = [_actions.c_compile],
flag_groups = [
flag_group(
flags = ["-std=" + std_version],
),
],
with_features = [
with_feature_set(
features = [std_version],
),
],
)
for std_version in _c_std_versions
],
))
return features
def _env_based_common_global_cflags(ctx):
flags = []
# The logic comes from https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/config/global.go;l=332;drc=af32e1ba3ffca6b552ac1ff6d14e5c3a5148cb80
auto_pattern_initialize = ctx.attr._auto_pattern_initialize[BuildSettingInfo].value
auto_uninitialize = ctx.attr._auto_uninitialize[BuildSettingInfo].value
if ctx.attr._auto_zero_initialize[BuildSettingInfo].value:
flags.extend(["-ftrivial-auto-var-init=zero", "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"])
elif auto_pattern_initialize:
flags.extend(["-ftrivial-auto-var-init=pattern"])
elif auto_uninitialize:
flags.extend(["-ftrivial-auto-var-init=uninitialized"])
else:
# Default to zero initialization.
flags.extend(["-ftrivial-auto-var-init=zero", "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"])
if ctx.attr._use_ccache[BuildSettingInfo].value or (not auto_pattern_initialize and not auto_uninitialize):
flags.extend(["-Wno-unused-command-line-argument"])
if ctx.attr._llvm_next[BuildSettingInfo].value:
flags.extend(["-Wno-error=single-bit-bitfield-constant-conversion"])
if ctx.attr._allow_unknown_warning_option[BuildSettingInfo].value:
flags.extend(["-Wno-error=unknown-warning-option"])
return flags
def _compiler_flag_features(ctx, target_arch, target_os, flags = []):
os_is_device = is_os_device(target_os)
compiler_flags = []
# Combine the toolchain's provided flags with the default ones.
compiler_flags.extend(flags)
compiler_flags.extend(_flags.compiler_flags)
compiler_flags.extend(_generated_config_constants.CommonGlobalCflags)
compiler_flags.extend(_env_based_common_global_cflags(ctx))
if os_is_device:
compiler_flags.extend(_generated_config_constants.DeviceGlobalCflags)
else:
compiler_flags.extend(_generated_config_constants.HostGlobalCflags)
# Default compiler flags for assembly sources.
asm_only_flags = _generated_config_constants.CommonGlobalAsflags
# Default C++ compile action only flags (No C)
cpp_only_flags = []
cpp_only_flags.extend(_generated_config_constants.CommonGlobalCppflags)
if os_is_device:
cpp_only_flags.extend(_generated_config_constants.DeviceGlobalCppflags)
else:
cpp_only_flags.extend(_generated_config_constants.HostGlobalCppflags)
# Default C compile action only flags (No C++)
c_only_flags = []
c_only_flags.extend(_generated_config_constants.CommonGlobalConlyflags)
# Flags that only apply in the external/ directory.
non_external_flags = _flags.non_external_defines
features = []
# TODO: disabled on windows
features.append(feature(
name = "pic",
enabled = False,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = ["-fPIC"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags"],
not_features = ["pie"],
),
],
),
],
))
features.append(feature(
name = "pie",
enabled = False,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = ["-fPIE"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags"],
not_features = ["pic"],
),
],
),
],
))
features.append(feature(
name = "non_external_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = non_external_flags,
),
],
with_features = [
with_feature_set(
not_features = ["external_compiler_flags"],
),
],
),
],
))
# bpf only needs the flag below instead of all the flags in
# common_compiler_flags
features.append(feature(
name = "bpf_compiler_flags",
enabled = False,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = ["-fdebug-prefix-map=/proc/self/cwd="],
),
],
),
],
))
features.append(feature(
name = "asm_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.assemble,
flag_groups = [
flag_group(
flags = asm_only_flags,
),
],
),
],
))
features.append(feature(
name = "cpp_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_compile],
flag_groups = [
flag_group(
flags = cpp_only_flags,
),
],
),
],
))
if c_only_flags:
features.append(feature(
name = "c_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.c_compile],
flag_groups = [
flag_group(
flags = c_only_flags,
),
],
),
],
))
features.append(feature(
name = "arm_isa_arm",
enabled = False,
provides = ["arm_isa"],
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = ["-fstrict-aliasing"],
),
],
),
],
))
features.append(feature(
name = "arm_isa_thumb",
enabled = target_arch == _arches.Arm,
provides = ["arm_isa"],
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = _generated_config_constants.ArmThumbCflags,
),
],
),
],
))
# Must follow arm_isa_thumb for flag ordering
features.append(feature(
name = "common_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = compiler_flags,
),
],
),
],
))
features.append(feature(
name = "external_compiler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = _generated_config_constants.ExternalCflags,
),
],
with_features = [
with_feature_set(
not_features = ["non_external_compiler_flags"],
),
],
),
],
))
# The user_compile_flags feature is used by Bazel to add --copt, --conlyopt,
# and --cxxopt values. Any features added above this call will thus appear
# earlier in the commandline than the user opts (so users could override
# flags set by earlier features). Anything after the user options are
# effectively non-overridable by users.
features.append(feature(
name = "user_compile_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
expand_if_available = "user_compile_flags",
flags = ["%{user_compile_flags}"],
iterate_over = "user_compile_flags",
),
],
),
],
))
# These cannot be overriden by the user.
features.append(feature(
name = "no_override_clang_global_copts",
enabled = True,
flag_sets = [
flag_set(
# We want this to apply to all actions except assembly
# primarily to match Soong's semantics
actions = [a for a in _actions.compile if a not in _actions.assemble],
flag_groups = [
flag_group(
flags = _generated_config_constants.NoOverrideGlobalCflags,
),
],
),
],
))
if target_os != _oses.Darwin:
# These cannot be overriden by the user.
features.append(feature(
name = "no_override_clang_external_global_copts",
enabled = True,
flag_sets = [
flag_set(
# We want this to apply to all actions except assembly
# primarily to match Soong's semantics
actions = [a for a in _actions.compile if a not in _actions.assemble],
flag_groups = [
flag_group(
flags = _generated_config_constants.NoOverrideExternalGlobalCflags,
),
],
),
],
requires = [
feature_set(features = [
"external_compiler_flags",
]),
],
))
return features
def _rtti_features(rtti_toggle):
if not rtti_toggle:
return []
rtti_flag_feature = feature(
name = "rtti_flag",
flag_sets = [
flag_set(
actions = [_actions.cpp_compile],
flag_groups = [
flag_group(
flags = ["-frtti"],
),
],
with_features = [
with_feature_set(features = ["rtti"]),
],
),
flag_set(
actions = [_actions.cpp_compile],
flag_groups = [
flag_group(
flags = ["-fno-rtti"],
),
],
with_features = [
with_feature_set(not_features = ["rtti"]),
],
),
],
enabled = True,
)
rtti_feature = feature(
name = "rtti",
enabled = False,
)
return [rtti_flag_feature, rtti_feature]
# TODO(b/202167934): Darwin does not support pack dynamic relocations
def _pack_dynamic_relocations_features(target_os):
sht_relr_flags = flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-Wl,--pack-dyn-relocs=android+relr"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags"],
not_features = ["disable_pack_relocations"] + _sdk_version_features_before(30),
),
],
)
android_relr_flags = flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-Wl,--pack-dyn-relocs=android+relr", "-Wl,--use-android-relr-tags"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags", version],
not_features = ["disable_pack_relocations"],
)
for version in _sdk_version_features_between(28, 29)
],
)
relocation_packer_flags = flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-Wl,--pack-dyn-relocs=android"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags", version],
not_features = ["disable_pack_relocations"],
)
for version in _sdk_version_features_between(23, 27)
],
)
if is_os_bionic(target_os):
pack_dyn_relr_flag_sets = [
sht_relr_flags,
android_relr_flags,
relocation_packer_flags,
]
else:
pack_dyn_relr_flag_sets = []
pack_dynamic_relocations_feature = feature(
name = "pack_dynamic_relocations",
enabled = True,
flag_sets = pack_dyn_relr_flag_sets,
)
disable_pack_relocations_feature = feature(
# this will take precedence over the pack_dynamic_relocations feature
# because each flag_set in that feature explicitly disallows the
# disable_dynamic_relocations feature
name = "disable_pack_relocations",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-Wl,--pack-dyn-relocs=none"],
),
],
with_features = [
with_feature_set(
features = ["linker_flags"],
),
],
),
],
enabled = False,
)
return [
pack_dynamic_relocations_feature,
disable_pack_relocations_feature,
]
# TODO(b/202167934): Darwin by default disallows undefined symbols, to allow, -Wl,undefined,dynamic_lookup
def _undefined_symbols_feature(target_os):
return _linker_flag_feature(
"no_undefined_symbols",
flags = ["-Wl,--no-undefined"],
enabled = is_os_bionic(target_os) or target_os == _oses.LinuxMusl,
)
def _dynamic_linker_flag_feature(target_os, arch_is_64_bit):
flags = []
if is_os_device(target_os):
# TODO: handle bootstrap partition, asan
dynamic_linker_path = "/system/bin/linker"
if arch_is_64_bit:
dynamic_linker_path += "64"
flags += ["-Wl,-dynamic-linker," + dynamic_linker_path]
elif is_os_bionic(target_os) or target_os == _oses.LinuxMusl:
flags += ["-Wl,--no-dynamic-linker"]
return _binary_linker_flag_feature(name = "dynamic_linker", flags = flags) if len(flags) else []
# TODO(b/202167934): Darwin uses @loader_path in place of $ORIGIN
def _rpath_features(target_os, arch_is_64_bit):
runtime_library_search_directories_flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
iterate_over = "runtime_library_search_directories",
flag_groups = [
flag_group(
flags = [
"-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}",
],
expand_if_true = "is_cc_test",
),
flag_group(
flags = [
"-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
],
expand_if_false = "is_cc_test",
),
],
expand_if_available =
"runtime_library_search_directories",
),
],
with_features = [
with_feature_set(features = ["static_link_cpp_runtimes"]),
],
),
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
iterate_over = "runtime_library_search_directories",
flag_groups = [
flag_group(
flags = [
"-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
],
),
],
expand_if_available =
"runtime_library_search_directories",
),
],
with_features = [
with_feature_set(
not_features = ["static_link_cpp_runtimes", "disable_rpath"],
),
],
),
]
if (not is_os_device(target_os)) and arch_is_64_bit:
runtime_library_search_directories_flag_sets += [flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flag_groups = [
flag_group(
flags = [
"-Wl,-rpath,$ORIGIN/../lib64",
"-Wl,-rpath,$ORIGIN/lib64",
],
),
],
),
],
with_features = [
with_feature_set(not_features = ["static_link_cpp_runtimes"]),
],
)]
runtime_library_search_directories_feature = feature(
name = "runtime_library_search_directories",
flag_sets = runtime_library_search_directories_flag_sets,
)
disable_rpath_feature = feature(
name = "disable_rpath",
enabled = False,
)
return [runtime_library_search_directories_feature, disable_rpath_feature]
def _use_libcrt_feature(path):
if not path:
return None
return _flag_feature("use_libcrt", actions = _actions.link, flags = [
path.path,
"-Wl,--exclude-libs=" + path.path,
])
def _flag_feature(name, actions = None, flags = None, enabled = True):
if not flags or not actions:
return None
return feature(
name = name,
enabled = enabled,
flag_sets = [
flag_set(
actions = actions,
flag_groups = [
flag_group(flags = flags),
],
),
],
)
def _linker_flag_feature(name, flags = [], enabled = True):
return _flag_feature(name, actions = _actions.link, flags = flags, enabled = enabled)
def _archiver_flag_feature(name, flags = [], enabled = True):
return _flag_feature(name, actions = _actions.archive, flags = flags, enabled = enabled)
def _binary_linker_flag_feature(name, flags = [], enabled = True):
return _flag_feature(name, actions = [_actions.cpp_link_executable], flags = flags, enabled = enabled)
def _toolchain_include_feature(system_includes = []):
flags = []
for include in system_includes:
flags.append("-isystem")
flags.append(include)
if not flags:
return None
return feature(
name = "toolchain_include_directories",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = flags,
),
],
),
],
)
def _stub_library_feature():
return feature(
name = "stub_library",
enabled = False,
flag_sets = [
flag_set(
actions = [_actions.c_compile],
flag_groups = [
flag_group(
# Ensures that the stub libraries are always compiled with default visibility
flags = _generated_config_constants.StubLibraryCompilerFlags + ["-fvisibility=default"],
),
],
),
],
)
def _flatten(xs):
ret = []
for x in xs:
if type(x) == "list":
ret.extend(x)
else:
ret.append(x)
return ret
def _additional_archiver_flags(target_os):
archiver_flags = []
if target_os != _oses.Darwin:
archiver_flags.extend(_flags.non_darwin_archiver_flags)
return archiver_flags
# Additional linker flags that are dependent on a host or device target.
def _additional_linker_flags(os_is_device):
linker_flags = []
if os_is_device:
linker_flags.extend(_generated_config_constants.DeviceGlobalLldflags)
linker_flags.extend(_flags.bionic_linker_flags)
else:
linker_flags.extend(_generated_config_constants.HostGlobalLldflags)
return linker_flags
def _static_binary_linker_flags(os_is_device):
linker_flags = []
if os_is_device:
linker_flags.extend(_flags.bionic_static_executable_linker_flags)
return linker_flags
def _shared_binary_linker_flags(target_os):
linker_flags = []
if is_os_device(target_os):
linker_flags.extend(_flags.bionic_dynamic_executable_linker_flags)
elif target_os != _oses.Windows:
linker_flags.extend(_flags.host_non_windows_dynamic_executable_linker_flags)
return linker_flags
# Legacy features moved from their hardcoded Bazel's Java implementation
# to Starlark.
#
# These legacy features must come before all other features.
def _get_legacy_features_begin():
features = [
# Legacy features omitted from this list, since they're not used in
# Android builds currently, or is alternatively supported through rules
# directly (e.g. stripped_shared_library for debug symbol stripping).
#
# thin_lto: Do not add, as it may break some features. replaced by _get_thinlto_features()
#
# runtime_library_search_directories: replaced by custom _rpath_feature().
#
# Compile related features:
#
# random_seed
# legacy_compile_flags
# per_object_debug_info
# pic
# force_pic_flags
#
# Optimization related features:
#
# fdo_instrument
# fdo_optimize
# cs_fdo_instrument
# cs_fdo_optimize
# fdo_prefetch_hints
# propeller_optimize
#
# Interface libraries related features:
#
# supports_interface_shared_libraries
# build_interface_libraries
# dynamic_library_linker_tool
#
# Coverage:
#
# coverage
# llvm_coverage_map_format
# gcc_coverage_map_format
#
# Others:
#
# symbol_counts
# static_libgcc
# fission_support
# static_link_cpp_runtimes
#
# ------------------------
#
feature(
name = "autofdo",
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/afdo.go;l=35;drc=7a8362c252b152f806fc303c414ff1418672b067
flags = [
"-funique-internal-linkage-names",
"-fprofile-sample-accurate",
"-fprofile-sample-use=%{fdo_profile_path}",
],
expand_if_available = "fdo_profile_path",
),
],
),
],
provides = ["profile"],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=98;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "dependency_file",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
expand_if_available = "dependency_file",
flags = [
"-MD",
"-MF",
"%{dependency_file}",
],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=186;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "preprocessor_defines",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
iterate_over = "preprocessor_defines",
flags = ["-D%{preprocessor_defines}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=207;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "includes",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
expand_if_available = "includes",
iterate_over = "includes",
flags = ["-include", "%{includes}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=232;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "include_paths",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
iterate_over = "quote_include_paths",
flags = ["-iquote", "%{quote_include_paths}"],
),
flag_group(
iterate_over = "include_paths",
flags = ["-I", "%{include_paths}"],
),
flag_group(
iterate_over = "system_include_paths",
flags = ["-isystem", "%{system_include_paths}"],
),
flag_group(
flags = ["-F%{framework_include_paths}"],
iterate_over = "framework_include_paths",
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=476;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "shared_flag",
flag_sets = [
flag_set(
actions = [
_actions.cpp_link_dynamic_library,
_actions.cpp_link_nodeps_dynamic_library,
],
flag_groups = [
flag_group(
flags = [
"-shared",
],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=492;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "linkstamps",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
expand_if_available = "linkstamp_paths",
iterate_over = "linkstamp_paths",
flags = ["%{linkstamp_paths}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=512;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "output_execpath_flags",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
expand_if_available = "output_execpath",
flags = [
"-o",
"%{output_execpath}",
],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=592;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "library_search_directories",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
expand_if_available = "library_search_directories",
iterate_over = "library_search_directories",
flags = ["-L%{library_search_directories}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=612;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "archiver_flags",
flag_sets = [
flag_set(
actions = ["c++-link-static-library"],
flag_groups = [
flag_group(
flags = ["crsPD"],
),
flag_group(
expand_if_available = "output_execpath",
flags = ["%{output_execpath}"],
),
],
),
flag_set(
actions = ["c++-link-static-library"],
flag_groups = [
flag_group(
expand_if_available = "libraries_to_link",
iterate_over = "libraries_to_link",
flag_groups = [
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file",
),
flags = ["%{libraries_to_link.name}"],
),
],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
iterate_over = "libraries_to_link.object_files",
flags = ["%{libraries_to_link.object_files}"],
),
],
),
],
),
feature(
name = "archive_with_prebuilt_flags",
flag_sets = [
flag_set(
actions = ["c++-link-static-library"],
flag_groups = [
flag_group(
flags = ["cqsL"],
),
flag_group(
expand_if_available = "output_execpath",
flags = ["%{output_execpath}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=653;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "libraries_to_link",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = ([
flag_group(
expand_if_true = "thinlto_param_file",
flags = ["-Wl,@%{thinlto_param_file}"],
),
flag_group(
expand_if_available = "libraries_to_link",
iterate_over = "libraries_to_link",
flag_groups = (
[
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--start-lib"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "static_library",
),
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--whole-archive"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
iterate_over = "libraries_to_link.object_files",
flags = ["%{libraries_to_link.object_files}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "interface_library",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "static_library",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "dynamic_library",
),
flags = ["-l%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "versioned_dynamic_library",
),
flags = ["-l:%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "static_library",
),
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--no-whole-archive"],
),
flag_group(
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--end-lib"],
),
]
),
),
]),
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=842;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "user_link_flags",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
expand_if_available = "user_link_flags",
iterate_over = "user_link_flags",
flags = ["%{user_link_flags}"],
),
],
),
],
),
feature(
name = "strip_debug_symbols",
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
expand_if_available = "strip_debug_symbols",
flags = ["-Wl,-S"],
),
],
),
],
enabled = False,
),
feature(
name = "llvm_coverage_map_format",
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-fprofile-instr-generate=/data/misc/trace/clang-%%p-%%m.profraw",
"-fcoverage-mapping",
"-Wno-pass-failed",
"-D__ANDROID_CLANG_COVERAGE__",
],
),
],
),
flag_set(
actions = [_actions.c_compile, _actions.cpp_compile],
flag_groups = [flag_group(flags = ["-Wno-frame-larger-than="])],
),
# TODO(b/233660582): support "-Wl,--wrap,open" and libprofile-clang-extras
flag_set(
actions = _actions.link,
flag_groups = [flag_group(flags = ["-fprofile-instr-generate"])],
),
flag_set(
actions = _actions.link,
flag_groups = [flag_group(flags = ["-Wl,--wrap,open"])],
with_features = [
with_feature_set(
features = ["android_coverage_lib"],
),
],
),
],
requires = [feature_set(features = ["coverage"])],
),
feature(name = "coverage"),
feature(name = "android_coverage_lib"),
]
return features
# Legacy features moved from their hardcoded Bazel's Java implementation
# to Starlark.
#
# These legacy features must come after all other features.
def _get_legacy_features_end():
# Omitted legacy (unused or re-implemented) features:
#
# fully_static_link
# user_compile_flags
# sysroot
features = [
feature(
name = "linker_param_file",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.link + _actions.archive,
flag_groups = [
flag_group(
expand_if_available = "linker_param_file",
flags = ["@%{linker_param_file}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=1511;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "compiler_input_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
expand_if_available = "source_file",
flags = ["-c", "%{source_file}"],
),
],
),
],
),
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=1538;drc=6d03a2ecf25ad596446c296ef1e881b60c379812
feature(
name = "compiler_output_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
expand_if_available = "output_assembly_file",
flags = ["-S"],
),
flag_group(
expand_if_available = "output_preprocess_file",
flags = ["-E"],
),
flag_group(
expand_if_available = "output_file",
flags = ["-o", "%{output_file}"],
),
],
),
],
),
]
return features
def _link_crtbegin(crt_files):
# in practice, either all of these are supported for a toolchain or none of them do
if crt_files.shared_library_crtbegin == None or crt_files.shared_binary_crtbegin == None or crt_files.static_binary_crtbegin == None:
return []
features = [
feature(
# User facing feature
name = "link_crt",
enabled = True,
implies = ["link_crtbegin", "link_crtend"],
),
feature(
name = "link_crtbegin",
enabled = True,
),
feature(
name = "link_crtbegin_so",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_link_dynamic_library],
flag_groups = [
flag_group(
flags = [crt_files.shared_library_crtbegin.path],
),
],
with_features = [
with_feature_set(
features = ["link_crt", "link_crtbegin"],
),
],
),
],
),
feature(
name = "link_crtbegin_dynamic",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_link_executable],
flag_groups = [
flag_group(
flags = [crt_files.shared_binary_crtbegin.path],
),
],
with_features = [
with_feature_set(
features = [
"dynamic_executable",
"link_crt",
"link_crtbegin",
],
),
],
),
],
),
feature(
name = "link_crtbegin_static",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_link_executable],
flag_groups = [
flag_group(
flags = [crt_files.static_binary_crtbegin.path],
),
],
with_features = [
with_feature_set(
features = [
"link_crt",
"link_crtbegin",
"static_executable",
],
),
],
),
],
),
]
return features
def _link_crtend(crt_files):
# in practice, either all of these are supported for a toolchain or none of them do
if crt_files.shared_library_crtend == None or crt_files.binary_crtend == None:
return None
return [
feature(
name = "link_crtend",
enabled = True,
),
feature(
name = "link_crtend_so",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_link_dynamic_library],
flag_groups = [
flag_group(
flags = [crt_files.shared_library_crtend.path],
),
],
with_features = [
with_feature_set(
features = ["link_crt", "link_crtend"],
),
],
),
],
),
feature(
name = "link_crtend_binary",
enabled = True,
flag_sets = [
flag_set(
actions = [_actions.cpp_link_executable],
flag_groups = [
flag_group(
flags = [crt_files.binary_crtend.path],
),
],
with_features = [
with_feature_set(
features = ["link_crt", "link_crtend"],
),
],
),
],
),
]
# TODO(b/276932249): Restrict for Fuzzer when we have Fuzzer in Bazel
def _get_thinlto_features():
features = [
feature(
name = "android_thin_lto",
enabled = False,
flag_sets = [
flag_set(
actions = _actions.compile + _actions.link + _actions.assemble,
flag_groups = [
flag_group(
flags = [
"-flto=thin",
"-fsplit-lto-unit",
],
),
],
),
],
),
feature(
name = "android_thin_lto_whole_program_vtables",
enabled = False,
requires = [feature_set(features = ["android_thin_lto"])],
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-fwhole-program-vtables"],
),
],
),
],
),
# See Soong code:
# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/lto.go;l=133;drc=2c435a00ff73dc485855824ee49d2dec1a01e592
feature(
name = "android_thin_lto_limit_cross_tu_inline",
enabled = True,
requires = [feature_set(features = ["android_thin_lto"])],
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = ["-Wl,-plugin-opt,-import-instr-limit=5"],
),
],
with_features = [
with_feature_set(
not_features = [
# TODO(b/267220812): Update for PGO
"autofdo",
],
),
],
),
],
),
]
return features
def _make_flag_set(actions, flags, with_features = [], with_not_features = []):
return flag_set(
actions = actions,
flag_groups = [
flag_group(
flags = flags,
),
],
with_features = [
with_feature_set(
features = with_features,
not_features = with_not_features,
),
],
)
# TODO(b/276756817): Restrict for VNDK when we have VNDK in Bazel
# TODO(b/276756319): Restrict for riscv64 when we have riscv64 in Bazel
# TODO(b/276932249): Restrict for Fuzzer when we have Fuzzer in Bazel
# TODO(b/276931992): Restrict for Asan when we have Asan in Bazel
def _get_cfi_features(target_arch, target_os):
if target_os in [_oses.Windows, _oses.Darwin, _oses.LinuxMusl]:
return []
features = [
feature(
name = "android_cfi",
enabled = False,
flag_sets = [
_make_flag_set(
_actions.c_and_cpp_compile,
_generated_sanitizer_constants.CfiCFlags,
),
_make_flag_set(
_actions.link,
_generated_sanitizer_constants.CfiLdFlags,
),
_make_flag_set(
_actions.assemble,
_generated_sanitizer_constants.CfiAsFlags,
),
],
implies = ["android_thin_lto"] + (
["arm_isa_thumb"] if target_arch == _arches.Arm else []
),
),
]
features += [
feature(
name = "android_cfi_cross_dso",
enabled = True,
requires = [feature_set(features = ["android_cfi"])],
flag_sets = [
_make_flag_set(
actions = _actions.c_and_cpp_compile + _actions.link,
flags = [_generated_sanitizer_constants.CfiCrossDsoFlag],
with_features = ["dynamic_executable"],
with_not_features = ["static_executable"],
),
],
),
]
features += [
feature(
name = "android_cfi_assembly_support",
enabled = False,
requires = [feature_set(features = ["android_cfi"])],
flag_sets = [
_make_flag_set(
_actions.c_and_cpp_compile,
[_generated_sanitizer_constants.CfiAssemblySupportFlag],
),
],
),
]
features += [
feature(
name = "android_cfi_exports_map",
enabled = False,
requires = [feature_set(features = ["android_cfi"])],
flag_sets = [
_make_flag_set(
_actions.link,
[
_generated_config_constants.VersionScriptFlagPrefix +
_generated_sanitizer_constants.CfiExportsMapPath +
"/" +
_generated_sanitizer_constants.CfiExportsMapFilename,
],
),
],
),
]
features += [
feature(
name = "android_cfi_visibility_default",
enabled = True,
requires = [feature_set(features = ["android_cfi"])],
flag_sets = [
flag_set(
actions = _actions.c_and_cpp_compile,
flag_groups = [
flag_group(
flags = [
_generated_config_constants.VisibilityDefaultFlag,
],
),
],
with_features = [
with_feature_set(
not_features = ["visibility_hidden"],
),
],
),
],
),
]
return features
def _get_visibiility_hidden_feature():
return [
feature(
name = "visibility_hidden",
enabled = False,
flag_sets = [
_make_flag_set(
_actions.c_and_cpp_compile,
[_generated_config_constants.VisibilityHiddenFlag],
),
],
),
]
def _ubsan_flag_feature(name, actions, flags):
return feature(
name = name,
enabled = True,
flag_sets = [
flag_set(
actions = actions,
flag_groups = [
flag_group(
flags = flags,
),
],
with_features = [
with_feature_set(
features = ["ubsan_enabled"],
),
],
),
],
)
def _host_or_device_specific_ubsan_feature(target_os):
if is_os_device(target_os):
return _ubsan_flag_feature(
"ubsan_device_only_flags",
_actions.compile,
_generated_sanitizer_constants.DeviceOnlySanitizeFlags,
)
return _ubsan_flag_feature(
"ubsan_host_only_flags",
_actions.compile,
_generated_sanitizer_constants.HostOnlySanitizeFlags,
)
def _exclude_ubsan_rt_feature(path):
if not path:
return None
return _ubsan_flag_feature(
"ubsan_exclude_rt",
_actions.link,
["-Wl,--exclude-libs=" + path.basename],
)
int_overflow_ignorelist_path = "build/soong/cc/config"
int_overflow_ignorelist_filename = "integer_overflow_blocklist.txt"
def _get_ubsan_features(target_os, libclang_rt_ubsan_minimal):
if target_os in [_oses.Windows, _oses.Darwin]:
return []
ALL_UBSAN_ACTIONS = _actions.compile + _actions.link + _actions.assemble
ubsan_features = [
feature(
name = "ubsan_enabled",
enabled = False,
),
]
ubsan_features += [
feature(
name = "ubsan_integer_overflow",
enabled = False,
flag_sets = [
flag_set(
actions = ALL_UBSAN_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-fsanitize=unsigned-integer-overflow",
"-fsanitize=signed-integer-overflow",
],
),
],
),
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-fsanitize-ignorelist=%s/%s" % (
int_overflow_ignorelist_path,
int_overflow_ignorelist_filename,
),
],
),
],
),
],
implies = ["ubsan_minimal_runtime", "ubsan_enabled"],
),
]
ubsan_checks = [
"alignment",
"bool",
"builtin",
"bounds",
"array-bounds",
"local-bounds",
"enum",
"float-cast-overflow",
"float-divide-by-zero",
"function",
"implicit-unsigned-integer-truncation",
"implicit-signed-integer-truncation",
"implicit-integer-sign-change",
"integer-divide-by-zero",
"nonnull-attribute",
"null",
"nullability-arg",
"nullability-assign",
"nullability-return",
"objc-cast",
"object-size",
"pointer-overflow",
"return",
"returns-nonnull-attribute",
"shift",
"shift-base",
"shift-exponent",
"unsigned-shift-base",
"signed-integer-overflow",
"unreachable",
"unsigned-integer-overflow",
"vla-bound",
"vptr",
# check groups
"undefined",
"implicit-integer-truncation",
"implicit-integer-arithmetic-value-change",
"implicit-conversion",
"integer",
"nullability",
]
ubsan_features += [
feature(
name = "ubsan_" + check_name,
enabled = False,
flag_sets = [
flag_set(
actions = ALL_UBSAN_ACTIONS,
flag_groups = [
flag_group(
flags = ["-fsanitize=%s" % check_name],
),
],
),
],
implies = ["ubsan_minimal_runtime", "ubsan_enabled"],
)
for check_name in ubsan_checks
]
ubsan_features += [
feature(
name = "ubsan_no_sanitize_link_runtime",
enabled = target_os in [
_oses.Android,
_oses.LinuxBionic,
_oses.LinuxMusl,
],
flag_sets = [
flag_set(
actions = _actions.link,
flag_groups = [
flag_group(
flags = [
"-fno-sanitize-link-runtime",
],
),
],
with_features = [
with_feature_set(
features = ["ubsan_enabled"],
),
],
),
],
),
]
# non-Bionic toolchain prebuilts are missing UBSan's vptr and function san.
# Musl toolchain prebuilts have vptr and function sanitizers, but enabling
# them implicitly enables RTTI which causes RTTI mismatch issues with
# dependencies.
ubsan_features += [
feature(
name = "ubsan_disable_unsupported_non_bionic_checks",
enabled = target_os not in [_oses.LinuxBionic, _oses.Android],
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-fno-sanitize=function,vptr",
],
),
],
with_features = [
with_feature_set(
features = ["ubsan_integer_overflow"],
),
] + [
with_feature_set(features = ["ubsan_" + check_name])
for check_name in ubsan_checks
],
),
],
),
]
ubsan_features += [
_host_or_device_specific_ubsan_feature(target_os),
_exclude_ubsan_rt_feature(libclang_rt_ubsan_minimal),
]
ubsan_features += [
feature(
name = "ubsan_minimal_runtime",
enabled = False,
flag_sets = [
flag_set(
actions = ALL_UBSAN_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-fsanitize-minimal-runtime",
"-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined",
],
),
],
),
],
),
]
ubsan_features += [
feature(
name = "ubsan_disable_unsupported_integer_checks",
enabled = True,
flag_sets = [
# TODO(b/119329758): If this bug is fixed, this shouldn't be
# needed anymore
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-fno-sanitize=implicit-integer-sign-change",
],
),
],
with_features = [
with_feature_set(
features = ["ubsan_integer"],
not_features = [
"ubsan_implicit-integer-sign-change",
],
),
],
),
# TODO(b/171275751): If this bug is fixed, this shouldn't be
# needed anymore
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-fno-sanitize=unsigned-shift-base",
],
),
],
with_features = [
with_feature_set(
features = ["ubsan_integer"],
not_features = [
"ubsan_unsigned-shift-base",
],
),
],
),
],
),
]
return ubsan_features
def _manual_binder_interface_feature():
return feature(
name = "do_not_check_manual_binder_interfaces",
enabled = False,
flag_sets = [
flag_set(
actions = _actions.compile,
flag_groups = [
flag_group(
flags = [
"-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES",
],
),
],
),
],
)
# Create the full list of features.
def get_features(
ctx,
builtin_include_dirs,
crt_files):
target_os = ctx.attr.target_os
target_arch = ctx.attr.target_arch
target_flags = ctx.attr.target_flags
compile_only_flags = ctx.attr.compiler_flags
linker_only_flags = ctx.attr.linker_flags
deviceMaxPageSize = ctx.attr._product_variables[ProductVariablesInfo].DeviceMaxPageSizeSupported
if deviceMaxPageSize and (target_arch == "arm" or target_arch == "arm64"):
linker_only_flags = ctx.attr.linker_flags + \
["-Wl,-z,max-page-size=" + deviceMaxPageSize]
libclang_rt_builtin = ctx.file.libclang_rt_builtin
libclang_rt_ubsan_minimal = ctx.file.libclang_rt_ubsan_minimal
rtti_toggle = ctx.attr.rtti_toggle
os_is_device = is_os_device(target_os)
arch_is_64_bit = target_arch.endswith("64")
# Aggregate all features in order.
# Note that the feature-list helper methods called below may return empty
# lists, depending on whether these features should be enabled. These are still
# listed in the below stanza as-is to preserve ordering.
features = [
# Do not depend on Bazel's built-in legacy features and action configs:
feature(name = "no_legacy_features"),
# This must always come first, after no_legacy_features.
_link_crtbegin(crt_files),
# Explicitly depend on a subset of legacy configs:
_get_legacy_features_begin(),
# get_c_std_features must come before _compiler_flag_features and user
# compile flags, as build targets may use copts/cflags to explicitly
# change the -std version to overwrite the defaults or c{,pp}_std attribute
# value.
_get_c_std_features(),
# Features tied to sdk version
_get_sdk_version_features(os_is_device, target_arch),
_compiler_flag_features(ctx, target_arch, target_os, target_flags + compile_only_flags),
_rpath_features(target_os, arch_is_64_bit),
_rtti_features(rtti_toggle),
_use_libcrt_feature(libclang_rt_builtin),
# Shared compile/link flags that should also be part of the link actions.
_linker_flag_feature("linker_target_flags", flags = target_flags),
# Link-only flags.
_linker_flag_feature("linker_flags", flags = linker_only_flags + _additional_linker_flags(os_is_device)),
_archiver_flag_feature("additional_archiver_flags", flags = _additional_archiver_flags(target_os)),
_undefined_symbols_feature(target_os),
_dynamic_linker_flag_feature(target_os, arch_is_64_bit),
_binary_linker_flag_feature("dynamic_executable", flags = _shared_binary_linker_flags(target_os)),
# distinct from other static flags as it can be disabled separately
_binary_linker_flag_feature("static_flag", flags = ["-static"], enabled = False),
# default for executables is dynamic linking
_binary_linker_flag_feature("static_executable", flags = _static_binary_linker_flags(os_is_device), enabled = False),
_pack_dynamic_relocations_features(target_os),
# System include directories features
_toolchain_include_feature(system_includes = builtin_include_dirs),
# Compiling stub.c sources to stub libraries
_stub_library_feature(),
_get_legacy_features_end(),
# Optimization
_get_thinlto_features(),
# Sanitizers
_get_cfi_features(target_arch, target_os),
_get_ubsan_features(target_os, libclang_rt_ubsan_minimal),
# Misc features
_get_visibiility_hidden_feature(),
# This must always come last.
_link_crtend(crt_files),
_manual_binder_interface_feature(),
]
return _flatten([f for f in features if f != None])