blob: c68e82774822fffee1e8283b45238960e5e1a812 [file]
# Copyright 2025 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.
"""Helper methods for legacy features"""
load("//cc:action_names.bzl", "ACTION_NAMES")
load(
"//cc:cc_toolchain_config_lib.bzl",
"action_config",
"feature",
"feature_set",
"flag_group",
"flag_set",
"get_profile_correction_flags",
"tool",
"variable_with_value",
"with_feature_set",
)
def get_legacy_features(ctx, platform, existing_feature_names, linker_tool_path):
"""The features added to all legacy toolchains
Note: these features won't be added to the crosstools that defines
no_legacy_features feature (e.g. ndk, apple, enclave crosstools). Those need
to be modified separately.
Args:
ctx: bazel rule context
platform: (str) One of 'linux' or 'mac'
existing_feature_names: ([str])
linker_tool_path: (str)
Returns:
([FeatureInfo])
"""
profile_correction_flags = get_profile_correction_flags(ctx)
result = []
if "legacy_compile_flags" not in existing_feature_names:
result.append(feature(
name = "legacy_compile_flags",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [
flag_group(
expand_if_available = "legacy_compile_flags",
iterate_over = "legacy_compile_flags",
flags = ["%{legacy_compile_flags}"],
),
],
)],
))
# Gcc options:
# -MD turns on .d file output as a side-effect (doesn't imply -E)
# -MM[D] enables user includes only, not system includes
# -MF <name> specifies the dotd file name
# Issues:
# -M[M] alone subverts actual .o output (implies -E)
# -M[M]D alone breaks some of the .d naming assumptions
# This combination gets user and system includes with specified name:
# -MD -MF <name>
if "dependency_file" not in existing_feature_names:
result.append(feature(
name = "dependency_file",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "dependency_file",
flags = ["-MD", "-MF", "%{dependency_file}"],
)],
)],
))
# GCC and Clang give randomized names to symbols which are defined in
# an anonymous namespace but have external linkage. To make
# computation of these deterministic, we want to override the
# default seed for the random number generator. It's safe to use
# any value which differs for all translation units; we use the
# path to the object file.
if "random_seed" not in existing_feature_names:
result.append(feature(
name = "random_seed",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
],
flag_groups = [flag_group(
expand_if_available = "output_file",
flags = ["-frandom-seed=%{output_file}"],
)],
)],
))
if "pic" not in existing_feature_names:
result.append(feature(
name = "pic",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "pic",
flags = ["-fPIC"],
)],
)],
))
if "per_object_debug_info" not in existing_feature_names:
result.append(feature(
name = "per_object_debug_info",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "per_object_debug_info_file",
flags = ["-gsplit-dwarf", "-g"],
)],
)],
))
if "preprocessor_defines" not in existing_feature_names:
result.append(feature(
name = "preprocessor_defines",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
iterate_over = "preprocessor_defines",
flags = ["-D%{preprocessor_defines}"],
)],
)],
))
if "includes" not in existing_feature_names:
result.append(feature(
name = "includes",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "includes",
iterate_over = "includes",
flags = ["-include", "%{includes}"],
)],
)],
))
if "include_paths" not in existing_feature_names:
result.append(feature(
name = "include_paths",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
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(
iterate_over = "framework_include_paths",
flags = ["-F%{framework_include_paths}"],
),
],
)],
))
if "fdo_instrument" not in existing_feature_names:
result.append(feature(
name = "fdo_instrument",
provides = ["profile"],
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [
flag_group(
expand_if_available = "fdo_instrument_path",
flags = ["-fprofile-generate=%{fdo_instrument_path}", "-fno-data-sections"],
),
],
)],
))
if "fdo_optimize" not in existing_feature_names:
result.append(feature(
name = "fdo_optimize",
provides = ["profile"],
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
],
flag_groups = [flag_group(
expand_if_available = "fdo_profile_path",
flags = [
"-fprofile-use=%{fdo_profile_path}",
"-Wno-profile-instr-unprofiled",
"-Wno-profile-instr-out-of-date",
] + profile_correction_flags,
)],
)],
))
if "cs_fdo_instrument" not in existing_feature_names:
result.append(feature(
name = "cs_fdo_instrument",
provides = ["csprofile"],
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_backend,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "cs_fdo_instrument_path",
flags = ["-fcs-profile-generate=%{cs_fdo_instrument_path}"],
)],
)],
))
if "cs_fdo_optimize" not in existing_feature_names:
result.append(feature(
name = "cs_fdo_optimize",
provides = ["csprofile"],
flag_sets = [flag_set(
actions = [ACTION_NAMES.lto_backend],
flag_groups = [flag_group(
expand_if_available = "fdo_profile_path",
flags = [
"-fprofile-use=%{fdo_profile_path}",
"-Wno-profile-instr-unprofiled",
"-Wno-profile-instr-out-of-date",
] + profile_correction_flags,
)],
)],
))
if "fdo_prefetch_hints" not in existing_feature_names:
result.append(feature(
name = "fdo_prefetch_hints",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.lto_backend,
],
flag_groups = [flag_group(
expand_if_available = "fdo_prefetch_hints_path",
flags = [
"-mllvm",
"-prefetch-hints-file=%{fdo_prefetch_hints_path}",
],
)],
)],
))
if "autofdo" not in existing_feature_names:
result.append(feature(
name = "autofdo",
provides = ["profile"],
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
],
flag_groups = [flag_group(
expand_if_available = "fdo_profile_path",
flags = [
"-fauto-profile=%{fdo_profile_path}",
] + profile_correction_flags,
)],
)],
))
if "propeller_optimize_thinlto_compile_actions" not in existing_feature_names:
result.append(feature(
name = "propeller_optimize_thinlto_compile_actions",
))
if "propeller_optimize" not in existing_feature_names:
result.append(feature(
name = "propeller_optimize",
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.lto_backend,
],
flag_groups = [flag_group(
expand_if_available = "propeller_optimize_cc_path",
flags = [
"-fbasic-block-sections=list=%{propeller_optimize_cc_path}",
"-DBUILD_PROPELLER_ENABLED=1",
],
)],
),
flag_set(
actions = [ACTION_NAMES.cpp_link_executable],
flag_groups = [flag_group(
expand_if_true = "propeller_optimize_ld_path",
flags = ["-Wl,--symbol-ordering-file=%{propeller_optimize_ld_path}"],
)],
),
],
))
if "build_interface_libraries" not in existing_feature_names:
result.append(feature(
name = "build_interface_libraries",
flag_sets = [flag_set(
with_features = [with_feature_set(
features = ["supports_interface_shared_libraries"],
)],
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "generate_interface_library",
flags = [
"%{generate_interface_library}",
"%{interface_library_builder_path}",
"%{interface_library_input_path}",
"%{interface_library_output_path}",
],
)],
)],
))
# Order of feature declaration matters, linker_tool_path has to
# follow right after build_interface_libraries.
if "dynamic_library_linker_tool" not in existing_feature_names:
result.append(feature(
name = "dynamic_library_linker_tool",
flag_sets = [flag_set(
with_features = [with_feature_set(
features = ["supports_interface_shared_libraries"],
)],
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "generate_interface_library",
flags = [linker_tool_path],
)],
)],
))
if "shared_flag" not in existing_feature_names:
result.append(feature(
name = "shared_flag",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(flags = ["-shared"])],
)],
))
if "linkstamps" not in existing_feature_names:
result.append(feature(
name = "linkstamps",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "linkstamp_paths",
iterate_over = "linkstamp_paths",
flags = ["%{linkstamp_paths}"],
)],
)],
))
if "output_execpath_flags" not in existing_feature_names:
result.append(feature(
name = "output_execpath_flags",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "output_execpath",
flags = ["-o", "%{output_execpath}"],
)],
)],
))
if "runtime_library_search_directories" not in existing_feature_names:
result.append(feature(
name = "runtime_library_search_directories",
flag_sets = [
flag_set(
with_features = [with_feature_set(
features = ["static_link_cpp_runtimes"],
)],
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [
flag_group(
expand_if_available = "runtime_library_search_directories",
iterate_over = "runtime_library_search_directories",
flag_groups = [
flag_group(
expand_if_true = "is_cc_test",
flags = [
# TODO(b/27153401): This should probably be @loader_path on osx.
"-Xlinker",
"-rpath",
"-Xlinker",
"$EXEC_ORIGIN/%{runtime_library_search_directories}",
],
),
flag_group(
expand_if_false = "is_cc_test",
flags = [
"-Xlinker",
"-rpath",
"-Xlinker",
_platform_specific_value(
platform,
linux = "$ORIGIN/%{runtime_library_search_directories}",
mac = "@loader_path/%{runtime_library_search_directories}",
),
],
),
],
),
],
),
flag_set(
with_features = [with_feature_set(
not_features = ["static_link_cpp_runtimes"],
)],
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "runtime_library_search_directories",
iterate_over = "runtime_library_search_directories",
flag_groups = [flag_group(
flags = [
"-Xlinker",
"-rpath",
"-Xlinker",
_platform_specific_value(
platform,
linux = "$ORIGIN/%{runtime_library_search_directories}",
mac = "@loader_path/%{runtime_library_search_directories}",
),
],
)],
)],
),
],
))
if "library_search_directories" not in existing_feature_names:
result.append(feature(
name = "library_search_directories",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "library_search_directories",
iterate_over = "library_search_directories",
flags = ["-L%{library_search_directories}"],
)],
)],
))
if "archiver_flags" not in existing_feature_names:
result.append(feature(
name = "archiver_flags",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.cpp_link_static_library],
flag_groups = [
flag_group(
flags = [_platform_specific_value(
platform,
linux = "rcsD",
mac = "-static",
)],
),
flag_group(
expand_if_available = "output_execpath",
flags = _platform_specific_value(
platform,
linux = [],
mac = ["-o"],
) + [
"%{output_execpath}",
],
),
],
),
flag_set(
actions = [ACTION_NAMES.cpp_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(
"libraries_to_link.type",
"object_file",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file_group",
),
iterate_over = "libraries_to_link.object_files",
flags = ["%{libraries_to_link.object_files}"],
),
],
),
],
),
],
))
if "libraries_to_link" not in existing_feature_names:
result.append(feature(
name = "libraries_to_link",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
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(
"libraries_to_link.type",
"object_file_group",
),
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--start-lib"],
),
] + _platform_specific_value(
platform,
linux = [
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"static_library",
),
flags = ["-Wl,-whole-archive"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file_group",
),
iterate_over = "libraries_to_link.object_files",
flags = ["%{libraries_to_link.object_files}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"interface_library",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"static_library",
),
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"dynamic_library",
),
flags = ["-l%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"versioned_dynamic_library",
),
flags = ["-l:%{libraries_to_link.name}"],
),
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"static_library",
),
flags = ["-Wl,-no-whole-archive"],
),
],
# macOS mirrors the linux behavior above with the following exceptions:
# - The -Wl,-whole-archive flags are excluded, as they are not supported on
# macOS.
# - Every expansion of libraries_to_link is split into a -Wl,-force_load
# version and a regular link version (with the exception of
# dynamic_library and versioned_dynamic_library).
# - versioned_dynamic_library has slightly different flag syntax on
# macOS.
mac = [
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file_group",
),
iterate_over = "libraries_to_link.object_files",
flag_groups = [
flag_group(
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["%{libraries_to_link.object_files}"],
),
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"],
),
],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file",
),
flag_groups = [
flag_group(
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
),
],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"interface_library",
),
flag_groups = [
flag_group(
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
),
],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"static_library",
),
flag_groups = [
flag_group(
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["%{libraries_to_link.name}"],
),
flag_group(
expand_if_true = "libraries_to_link.is_whole_archive",
flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
),
],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"dynamic_library",
),
flags = ["-l%{libraries_to_link.name}"],
),
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"versioned_dynamic_library",
),
flags = ["%{libraries_to_link.path}"],
),
],
) + [
flag_group(
expand_if_equal = variable_with_value(
"libraries_to_link.type",
"object_file_group",
),
expand_if_false = "libraries_to_link.is_whole_archive",
flags = ["-Wl,--end-lib"],
),
],
),
],
)],
))
if "force_pic_flags" not in existing_feature_names:
result.append(feature(
name = "force_pic_flags",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.lto_index_for_executable,
],
flag_groups = [flag_group(
expand_if_available = "force_pic",
flags = [
_platform_specific_value(
platform,
linux = "-pie",
mac = "-Wl,-pie",
),
],
)],
)],
))
if "user_link_flags" not in existing_feature_names:
result.append(feature(
name = "user_link_flags",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "user_link_flags",
iterate_over = "user_link_flags",
flags = ["%{user_link_flags}"],
)],
)],
))
if "legacy_link_flags" not in existing_feature_names:
result.append(feature(
name = "legacy_link_flags",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "legacy_link_flags",
iterate_over = "legacy_link_flags",
flags = ["%{legacy_link_flags}"],
)],
)],
))
if "static_libgcc" not in existing_feature_names:
result.append(feature(
name = "static_libgcc",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
],
with_features = [
with_feature_set(features = ["static_link_cpp_runtimes"]),
],
flag_groups = [flag_group(flags = ["-static-libgcc"])],
)],
))
if "fission_support" not in existing_feature_names:
result.append(feature(
name = "fission_support",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "is_using_fission",
flags = ["-Wl,--gdb-index"],
)],
)],
))
if "strip_debug_symbols" not in existing_feature_names:
result.append(feature(
name = "strip_debug_symbols",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "strip_debug_symbols",
flags = ["-Wl,-S"],
)],
)],
))
if "coverage" not in existing_feature_names:
result.extend([
feature(name = "coverage"),
feature(
name = "llvm_coverage_map_format",
provides = ["profile"],
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(flags = [
"-fprofile-instr-generate",
"-fcoverage-mapping",
])],
),
flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
ACTION_NAMES.objc_executable,
ACTION_NAMES.objcpp_executable,
],
flag_groups = [flag_group(flags = ["-fprofile-instr-generate"])],
),
],
requires = [feature_set(features = ["coverage"])],
),
feature(
name = "gcc_coverage_map_format",
provides = ["profile"],
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objc_executable,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.objcpp_executable,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "gcov_gcno_file",
flags = ["-fprofile-arcs", "-ftest-coverage"],
)],
),
flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(flags = ["--coverage"])],
),
],
requires = [feature_set(features = ["coverage"])],
),
])
return result
def get_features_to_appear_last(existing_feature_names):
"""Set of legacy features to append at the end of the feature list
Note: these feaures won't be added to the crosstools that defines
no_legacy_features feature (e.g. ndk, apple, enclave crosstools). Those need
to be modified separately.
Args:
existing_feature_names: (str)
Returns:
([FeatureInfo])
"""
result = []
if "fully_static_link" not in existing_feature_names:
result.append(feature(
name = "fully_static_link",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
],
flag_groups = [flag_group(flags = ["-static"])],
)],
))
if "user_compile_flags" not in existing_feature_names:
result.append(feature(
name = "user_compile_flags",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "user_compile_flags",
iterate_over = "user_compile_flags",
flags = ["%{user_compile_flags}"],
)],
)],
))
if "sysroot" not in existing_feature_names:
result.append(feature(
name = "sysroot",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "sysroot",
flags = ["--sysroot=%{sysroot}"],
)],
)],
))
# unfiltered_compile_flags contain system include paths. These must be added
# after the user provided options (present in legacy_compile_flags build
# variable above), otherwise users adding include paths will not pick up their
# own include paths first.
if "unfiltered_compile_flags" not in existing_feature_names:
result.append(feature(
name = "unfiltered_compile_flags",
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "unfiltered_compile_flags",
iterate_over = "unfiltered_compile_flags",
flags = ["%{unfiltered_compile_flags}"],
)],
)],
))
if "linker_param_file" not in existing_feature_names:
result.append(feature(
name = "linker_param_file",
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
ACTION_NAMES.lto_index_for_dynamic_library,
ACTION_NAMES.lto_index_for_executable,
ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
],
flag_groups = [flag_group(
expand_if_available = "linker_param_file",
flags = ["@%{linker_param_file}"],
)],
),
flag_set(
actions = [
ACTION_NAMES.cpp_link_static_library,
],
flag_groups = [flag_group(
expand_if_available = "linker_param_file",
flags = ["@%{linker_param_file}"],
)],
),
],
))
if "compiler_input_flags" not in existing_feature_names:
result.append(feature(
name = "compiler_input_flags",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
flag_groups = [flag_group(
expand_if_available = "source_file",
flags = ["-c", "%{source_file}"],
)],
)],
))
if "compiler_output_flags" not in existing_feature_names:
result.append(feature(
name = "compiler_output_flags",
enabled = True,
flag_sets = [flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.lto_backend,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
ACTION_NAMES.preprocess_assemble,
],
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 result
def get_legacy_action_configs(
platform,
gcc_tool_path,
ar_tool_path,
strip_tool_path,
existing_action_config_names):
"""The list of action configs added to all legacy toolchains
Note: these configs won't be added to the crosstools that defines
no_legacy_features feature (e.g. ndk, apple, enclave crosstools). Those need
to be modified separately.
Args:
platform: (str) 'mac' or 'linux'
gcc_tool_path: (str)
ar_tool_path: (str)
strip_tool_path: (str)
existing_action_config_names: ([str])
Returns:
([ActionConfigInfo])
"""
result = []
for action_name in [
"assemble",
"preprocess-assemble",
"linkstamp-compile",
"lto-backend",
"c-compile",
"c++-compile",
"c++-header-parsing",
"c++-module-compile",
"c++-module-codegen",
]:
if action_name not in existing_action_config_names:
result.append(action_config(
action_name = action_name,
tools = [tool(path = gcc_tool_path)],
implies = [
"legacy_compile_flags",
"user_compile_flags",
"sysroot",
"unfiltered_compile_flags",
"compiler_input_flags",
"compiler_output_flags",
],
))
for action_name in [
"c++-link-executable",
"lto-index-for-executable",
]:
if action_name not in existing_action_config_names:
result.append(action_config(
action_name = action_name,
tools = [tool(path = gcc_tool_path)],
implies = [
"strip_debug_symbols",
"linkstamps",
"output_execpath_flags",
"runtime_library_search_directories",
"library_search_directories",
"libraries_to_link",
"force_pic_flags",
"user_link_flags",
"legacy_link_flags",
"linker_param_file",
"fission_support",
"sysroot",
],
))
for action_name in [
"c++-link-nodeps-dynamic-library",
"lto-index-for-nodeps-dynamic-library",
"c++-link-dynamic-library",
"lto-index-for-dynamic-library",
]:
if action_name not in existing_action_config_names:
result.append(action_config(
action_name = action_name,
tools = [tool(path = gcc_tool_path)],
implies = [
"build_interface_libraries",
"dynamic_library_linker_tool",
"strip_debug_symbols",
"shared_flag",
"linkstamps",
"output_execpath_flags",
"runtime_library_search_directories",
"library_search_directories",
"libraries_to_link",
"user_link_flags",
"legacy_link_flags",
"linker_param_file",
"fission_support",
"sysroot",
],
))
if "c++-link-static-library" not in existing_action_config_names:
result.append(action_config(
action_name = "c++-link-static-library",
tools = [tool(path = ar_tool_path)],
implies = ["archiver_flags", "linker_param_file"],
))
if "strip" not in existing_action_config_names:
result.append(action_config(
action_name = "strip",
tools = [tool(path = strip_tool_path)],
flag_sets = [flag_set(
flag_groups = [
flag_group(
flags = ["-S"] + _platform_specific_value(
platform,
linux = ["-p"],
mac = [],
) + ["-o", "%{output_file}"],
),
flag_group(
iterate_over = "stripopts",
flags = ["%{stripopts}"],
),
flag_group(flags = ["%{input_file}"]),
],
)],
))
return result
def _platform_specific_value(platform, *, linux, mac):
if platform == "linux":
return linux
if platform == "mac":
return mac
fail("unexpected platform:", platform)