blob: aafac7efcf62de6c6a2c40f076ed132f667153bc [file] [log] [blame]
# Copyright 2023 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.
""" Default implementation of Bazel's exec transition ('cfg = "exec"').
See https://github.com/bazelbuild/bazel/discussions/19213.
"""
# The fragments that make up Bazel's exec transition. The fragment() calls in
# this file fill out this map.
bazel_fragments = {}
def fragment(propagate = [], inputs = [], outputs = [], func = lambda setting: {}):
"""Adds exec transition logic for a group of related flags.
Args:
propagate: Flags to propagate as-is from the input configuration.
inputs: Flags to specially read for custom transit logic.
outputs: Flags to specially write with custom transition logic.
func: Custom transition logic for flags we don't auto-propagate.
Returns:
The fragment.
"""
return struct(
inputs = inputs + propagate,
outputs = outputs + propagate,
propagate = propagate,
custom_logic = func,
)
def exec_transition(fragments):
"""Returns the data for creating an exec transition from a set of fragments.
Ideally this would create and return the transition itself. Instead, callers
have to wrap their own transition() call around the data returned here.
This is because Bazel checks if a transition is the exec transition, and if
so applies different implementation logic vs. normal transitions. The check,
at https://github.com/bazelbuild/bazel/blob/c8afa82026977e84d1c89f4f0ae3503ef7720a25/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java#L128-L130,
compares the value of `--experimental_exec_config` with the .bzl file that
declared the transition.
If another .bzl file wraps this logic for its own transition, it must
declare its own transition() call so that check matches (so Bazel sees the
owner of that transition is the other bzl file, not this one).
Args:
fragments: Fragments that make up the transition, as a map from name to
data. Data comes from the fragment() function.
Returns:
The data needd to declare an exec transition for those fragments.
"""
inputs_and_outputs = _get_inputs_and_outputs(fragments)
return struct(
implementation = _exec_transition_impl(fragments),
inputs = inputs_and_outputs.inputs,
outputs = inputs_and_outputs.outputs,
)
def _get_inputs_and_outputs(fragments):
"""Returns the (inputs, outputs) for a collection of fragments.
"""
inputs = []
outputs = ["//command_line_option:experimental_action_listener"]
for fragment in fragments.values():
inputs.extend(fragment.inputs)
outputs.extend(fragment.outputs)
return struct(inputs = inputs, outputs = outputs)
def _exec_transition_impl(fragments):
"""Returns an exec transition impl function from a set of fragments.
Args:
fragments: Fragments that make up the transition, as a map from name to
data. Data comes from the fragment() function.
"""
# buildifier: disable=unused-variable
def _impl(settings, attr):
ans = {}
for fragment in fragments.values():
for option in fragment.propagate:
ans[option] = settings[option]
ans.update(fragment.custom_logic(settings))
# Building with --experimental_action_listener fails.
# TODO(b/301654253): clarify what to do with this flag.
ans["//command_line_option:experimental_action_listener"] = []
return ans
return _impl
################################ Fragment definitions: #########################
#
# Fragments encapsulate thematically related flags (like all flags that
# configure Java rules). Fragments are not a native Bazel concept - they're pure
# Starlark collections.
bazel_fragments["AndroidConfiguration.Options"] = fragment(
propagate = [
"//command_line_option:android_crosstool_top",
"//command_line_option:android_sdk",
"//command_line_option:incompatible_enable_android_toolchain_resolution",
"//command_line_option:incompatible_android_platforms_transition_updated_affected",
"//command_line_option:desugar_for_android",
"//command_line_option:desugar_java8_libs",
"//command_line_option:experimental_check_desugar_deps",
"//command_line_option:incremental_dexing",
"//command_line_option:experimental_incremental_dexing_after_proguard",
"//command_line_option:experimental_use_dex_splitter_for_incremental_dexing",
"//command_line_option:experimental_incremental_dexing_after_proguard_by_default",
"//command_line_option:experimental_android_assume_minsdkversion",
"//command_line_option:non_incremental_per_target_dexopts",
"//command_line_option:dexopts_supported_in_incremental_dexing",
"//command_line_option:dexopts_supported_in_dexmerger",
"//command_line_option:dexopts_supported_in_dexsharder",
"//command_line_option:android_manifest_merger",
"//command_line_option:android_manifest_merger_order",
"//command_line_option:experimental_allow_android_library_deps_without_srcs",
"//command_line_option:experimental_one_version_enforcement_use_transitive_jars_for_binary_under_test",
"//command_line_option:internal_persistent_busybox_tools",
"//command_line_option:internal_persistent_multiplex_busybox_tools",
"//command_line_option:incompatible_disable_native_android_rules",
],
outputs = [
"//command_line_option:android hwasan",
"//command_line_option:fat_apk_cpu",
"//command_line_option:Android configuration distinguisher",
],
func = lambda settings: {
"//command_line_option:android hwasan": False,
"//command_line_option:fat_apk_cpu": [],
"//command_line_option:Android configuration distinguisher": "main",
},
)
# AndroidLocalTestConfiguration$Options: no exec configs
bazel_fragments["AppleCommandLineOptions"] = fragment(
propagate = [
"//command_line_option:xcode_version_config",
"//command_line_option:xcode_version",
"//command_line_option:ios_sdk_version",
"//command_line_option:watchos_sdk_version",
"//command_line_option:tvos_sdk_version",
"//command_line_option:macos_sdk_version",
"//command_line_option:host_macos_minimum_os",
"//command_line_option:experimental_prefer_mutual_xcode",
"//command_line_option:experimental_include_xcode_execution_requirements",
"//command_line_option:apple_crosstool_top",
"//command_line_option:incompatible_enable_apple_toolchain_resolution",
],
outputs = [
"//command_line_option:macos_minimum_os",
"//command_line_option:apple_platform_type",
"//command_line_option:apple configuration distinguisher",
],
func = lambda settings: {
"//command_line_option:macos_minimum_os": settings["//command_line_option:host_macos_minimum_os"],
"//command_line_option:apple_platform_type": "macos",
"//command_line_option:apple configuration distinguisher": "unknown",
},
)
bazel_fragments["BazelConfigurarion$Options"] = fragment(
propagate = [
"//command_line_option:incompatible_check_visibility_for_toolchains",
],
)
bazel_fragments["BazelPythonConfiguration$Options"] = fragment(
propagate = [
"//command_line_option:python2_path",
"//command_line_option:python3_path",
"//command_line_option:python_top",
"//command_line_option:python_path",
"//command_line_option:experimental_python_import_all_repositories",
],
)
bazel_fragments["BazelRuleClassProvider$StrictActionEnvOptions"] = fragment(
propagate = [
"//command_line_option:incompatible_strict_action_env",
],
)
bazel_fragments["ConfigFeatureFlagOptions"] = fragment(
propagate = [
"//command_line_option:all feature flag values are present (internal)",
],
outputs = [
"//command_line_option:enforce_transitive_configs_for_config_feature_flag",
],
func = lambda settings: {
"//command_line_option:enforce_transitive_configs_for_config_feature_flag": False,
},
)
def _core_options(settings):
ans = {
"//command_line_option:compilation_mode": settings["//command_line_option:host_compilation_mode"],
"//command_line_option:is exec configuration": True,
"//command_line_option:cpu": settings["//command_line_option:host_cpu"],
"//command_line_option:stamp": False,
"//command_line_option:action_env": settings["//command_line_option:host_action_env"],
}
if settings["//command_line_option:incompatible_use_host_features"]:
ans["//command_line_option:features"] = settings["//command_line_option:host_features"]
else:
ans["//command_line_option:features"] = settings["//command_line_option:features"]
return ans
bazel_fragments["CoreOptions"] = fragment(
propagate = [
"//command_line_option:experimental_output_directory_naming_scheme",
"//command_line_option:host_compilation_mode",
"//command_line_option:experimental_exec_configuration_distinguisher",
"//command_line_option:experimental_output_paths",
"//command_line_option:enable_runfiles",
"//command_line_option:enforce_constraints",
"//command_line_option:incompatible_merge_genfiles_directory",
"//command_line_option:experimental_platform_in_output_dir",
"//command_line_option:host_cpu",
"//command_line_option:include_config_fragments_provider",
"//command_line_option:experimental_debug_selects_always_succeed",
"//command_line_option:incompatible_check_testonly_for_output_files",
"//command_line_option:incompatible_auto_exec_groups",
"//command_line_option:experimental_writable_outputs",
"//command_line_option:build_runfile_manifests",
"//command_line_option:build_runfile_links",
"//command_line_option:legacy_external_runfiles",
"//command_line_option:experimental_remotable_source_manifests",
"//command_line_option:incompatible_always_include_files_in_data",
"//command_line_option:experimental_strict_fileset_output",
"//command_line_option:strict_filesets",
"//command_line_option:check_visibility",
"//command_line_option:check_licenses",
"//command_line_option:incompatible_use_host_features",
"//command_line_option:host_features",
"//command_line_option:host_action_env",
"//command_line_option:archived_tree_artifact_mnemonics_filter",
"//command_line_option:allow_unresolved_symlinks",
"//command_line_option:experimental_exec_config",
"//command_line_option:experimental_exclude_defines_from_exec_config",
"//command_line_option:experimental_exclude_starlark_flags_from_exec_config",
"//command_line_option:experimental_propagate_custom_flag",
],
inputs = ["//command_line_option:features"],
outputs = [
"//command_line_option:compilation_mode",
"//command_line_option:is exec configuration",
"//command_line_option:cpu",
"//command_line_option:stamp",
"//command_line_option:features",
"//command_line_option:action_env",
],
func = _core_options,
)
# CoverageConfiguration$CoverageOptions: no getExec()
bazel_fragments["CppOptions"] = fragment(
propagate = [
"//command_line_option:host_copt",
"//command_line_option:host_conlyopt",
"//command_line_option:host_compiler",
"//command_line_option:host_crosstool_top",
"//command_line_option:host_cxxopt",
"//command_line_option:host_per_file_copt",
"//command_line_option:host_grte_top",
"//command_line_option:host_linkopt",
"//command_line_option:target libcTop label",
"//command_line_option:experimental_link_static_libraries_once",
"//command_line_option:experimental_cc_implementation_deps",
"//command_line_option:start_end_lib",
"//command_line_option:experimental_inmemory_dotd_files",
"//command_line_option:incompatible_disable_legacy_cc_provider",
"//command_line_option:incompatible_enable_cc_toolchain_resolution",
"//command_line_option:incompatible_remove_legacy_whole_archive",
"//command_line_option:incompatible_dont_enable_host_nonhost_crosstool_features",
"//command_line_option:incompatible_require_ctx_in_configure_features",
"//command_line_option:incompatible_make_thinlto_command_lines_standalone",
"//command_line_option:incompatible_use_specific_tool_files",
"//command_line_option:incompatible_disable_nocopts",
"//command_line_option:incompatible_validate_top_level_header_inclusions",
"//command_line_option:strict_system_includes",
"//command_line_option:experimental_use_cpp_compile_action_args_params_file",
"//command_line_option:experimental_unsupported_and_brittle_include_scanning",
"//command_line_option:incompatible_enable_cc_test_feature",
"//command_line_option:incompatible_use_cpp_compile_header_mnemonic",
"//command_line_option:experimental_starlark_cc_import",
"//command_line_option:incompatible_macos_set_install_name",
],
outputs = [
"//command_line_option:crosstool_top",
"//command_line_option:compiler",
"//command_line_option:grte_top",
"//command_line_option:copt",
"//command_line_option:cxxopt",
"//command_line_option:conlyopt",
"//command_line_option:per_file_copt",
"//command_line_option:linkopt",
"//command_line_option:strip",
],
func = lambda settings: {
"//command_line_option:crosstool_top": settings["//command_line_option:host_crosstool_top"],
"//command_line_option:compiler": settings["//command_line_option:host_compiler"],
"//command_line_option:grte_top": settings["//command_line_option:host_grte_top"],
"//command_line_option:copt": settings["//command_line_option:host_copt"] + ["-g0"], # Don't add for Windows
"//command_line_option:cxxopt": settings["//command_line_option:host_cxxopt"] + ["-g0"], # Don't add for Windows
"//command_line_option:conlyopt": settings["//command_line_option:host_conlyopt"],
"//command_line_option:per_file_copt": settings["//command_line_option:host_per_file_copt"],
"//command_line_option:linkopt": settings["//command_line_option:host_linkopt"],
"//command_line_option:strip": "always",
},
)
# GenQueryConfiguration$GenQueryOptions: no getExec()
bazel_fragments["J2ObjcCommandLineOptions"] = fragment(
propagate = [
"//command_line_option:j2objc_translation_flags",
"//command_line_option:incompatible_j2objc_library_migration",
],
)
def _java_options(settings):
ans = {}
if settings["//command_line_option:host_jvmopt"] == []:
ans["//command_line_option:jvmopt"] = ["-XX:ErrorFile=/dev/stderr"]
else:
ans["//command_line_option:jvmopt"] = settings["//command_line_option:host_jvmopt"]
ans["//command_line_option:javacopt"] = settings["//command_line_option:host_javacopt"]
ans["//command_line_option:java_launcher"] = settings["//command_line_option:host_java_launcher"]
ans["//command_line_option:java_language_version"] = settings["//command_line_option:tool_java_language_version"]
ans["//command_line_option:java_runtime_version"] = settings["//command_line_option:tool_java_runtime_version"]
return ans
bazel_fragments["JavaOptions"] = fragment(
propagate = [
"//command_line_option:use_ijars",
"//command_line_option:java_header_compilation",
"//command_line_option:java_deps",
"//command_line_option:experimental_java_classpath",
"//command_line_option:experimental_inmemory_jdeps_files",
"//command_line_option:experimental_strict_java_deps",
"//command_line_option:experimental_fix_deps_tool",
"//command_line_option:experimental_one_version_enforcement",
"//command_line_option:experimental_import_deps_checking",
"//command_line_option:one_version_enforcement_on_java_tests",
"//command_line_option:experimental_allow_runtime_deps_on_neverlink",
"//command_line_option:experimental_add_test_support_to_compile_time_deps",
"//command_line_option:jplPropagateCcLinkParamsStore",
"//command_line_option:incompatible_disallow_resource_jars",
"//command_line_option:java_runtime_version",
"//command_line_option:java_language_version",
"//command_line_option:experimental_bytecode_optimizers",
"//command_line_option:split_bytecode_optimization_pass",
"//command_line_option:bytecode_optimization_pass_actions",
"//command_line_option:enforce_proguard_file_extension",
"//command_line_option:proguard_top",
"//command_line_option:host_javacopt",
"//command_line_option:host_java_launcher",
"//command_line_option:tool_java_runtime_version",
"//command_line_option:tool_java_language_version",
"//command_line_option:experimental_turbine_annotation_processing",
"//command_line_option:incompatible_multi_release_deploy_jars",
"//command_line_option:incompatible_disallow_java_import_exports",
"//command_line_option:incompatible_disallow_java_import_empty_jars",
],
inputs = [
"//command_line_option:host_jvmopt",
],
outputs = [
"//command_line_option:jvmopt",
"//command_line_option:javacopt",
"//command_line_option:java_launcher",
],
func = _java_options,
)
bazel_fragments["ObjcCommandLineOptions"] = fragment(
propagate = [
"//command_line_option:incompatible_avoid_hardcoded_objc_compilation_flags",
"//command_line_option:incompatible_disallow_sdk_frameworks_attributes",
"//command_line_option:incompatible_objc_alwayslink_by_default",
"//command_line_option:incompatible_strip_executable_safely",
],
)
bazel_fragments["PlatformOptions"] = fragment(
propagate = [
"//command_line_option:host_platform",
"//command_line_option:platform_mappings",
"//command_line_option:extra_execution_platforms",
"//command_line_option:extra_toolchains",
"//command_line_option:toolchain_resolution_debug",
"//command_line_option:incompatible_use_toolchain_resolution_for_java_rules",
],
)
bazel_fragments["ProtoConfiguration$Options"] = fragment(
propagate = [
"//command_line_option:proto_compiler",
"//command_line_option:protocopt",
"//command_line_option:experimental_proto_descriptor_sets_include_source_info",
"//command_line_option:experimental_proto_extra_actions",
"//command_line_option:proto_toolchain_for_java",
"//command_line_option:proto_toolchain_for_j2objc",
"//command_line_option:proto_toolchain_for_javalite",
"//command_line_option:proto_toolchain_for_cc",
"//command_line_option:strict_proto_deps",
"//command_line_option:strict_public_imports",
"//command_line_option:cc_proto_library_header_suffixes",
"//command_line_option:cc_proto_library_source_suffixes",
],
)
def _python_options(settings):
if settings["//command_line_option:host_force_python"] != None:
host_py_version = settings["//command_line_option:host_force_python"]
elif settings["//command_line_option:incompatible_py3_is_default"]:
host_py_version = "py3"
else:
host_py_version = "py2"
return {
"//command_line_option:python_version": host_py_version,
}
bazel_fragments["PythonOptions"] = fragment(
# Could move these toolchain configuring flags to toolchain definitions?
# And not make them flags. Must each one toggle independently of the others?
propagate = [
"//command_line_option:incompatible_py3_is_default",
"//command_line_option:incompatible_py2_outputs_are_suffixed",
"//command_line_option:build_python_zip",
"//command_line_option:incompatible_use_python_toolchains",
"//command_line_option:incompatible_allow_python_version_transitions",
"//command_line_option:incompatible_default_to_explicit_init_py",
"//command_line_option:incompatible_disallow_legacy_py_provider",
"//command_line_option:incompatible_remove_old_python_version_api",
"//command_line_option:incompatible_python_disable_py2",
"//command_line_option:python_native_rules_allowlist",
"//command_line_option:incompatible_python_disallow_native_rules",
"//command_line_option:host_force_python",
],
outputs = [
"//command_line_option:python_version",
],
func = _python_options,
)
bazel_fragments["ShellConfiguration$Options"] = fragment(
propagate = [
"//command_line_option:shell_executable",
],
)
# TestConfiguration$TestOptions: handled in native code. See b/295936652.
# Bazel's exec transition.
_transition_data = exec_transition(bazel_fragments)
bazel_exec_transition = _builtins.toplevel.transition(
implementation = _transition_data.implementation,
inputs = _transition_data.inputs,
outputs = _transition_data.outputs,
)