| # 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. | |
| """ | |
| All build variables we create for various `CppCompileAction`s | |
| """ | |
| load("//cc/common:cc_helper_internal.bzl", "extensions", "get_fdo_build_stamp", "get_linkstamp_stamps", _PRIVATE_STARLARKIFICATION_ALLOWLIST = "PRIVATE_STARLARKIFICATION_ALLOWLIST") | |
| load("//cc/private:cc_info.bzl", "get_module_map_name") | |
| load("//cc/private:cc_internal.bzl", _cc_internal = "cc_internal") | |
| load("//cc/private/rules_impl:native_cc_common.bzl", _cc_common_internal = "native_cc_common") | |
| # deliberately short name for less clutter while using in this file, we can have | |
| # a different symbol with a more descriptive name if we ever export this | |
| _VARS = struct( | |
| # Variable for the collection of framework include paths. | |
| FRAMEWORK_PATHS = "framework_include_paths", | |
| # Variable for the path to the source file being compiled. | |
| SOURCE_FILE = "source_file", | |
| # Variable for all flags coming from copt rule attribute, and from --copt, | |
| # --cxxopt, or --conlyopt options. | |
| USER_COMPILE_FLAGS = "user_compile_flags", | |
| # Variable for the path to the compilation output file. | |
| OUTPUT_FILE = "output_file", | |
| # Variable for the dependency file path | |
| DEPENDENCY_FILE = "dependency_file", | |
| # Variable for the serialized diagnostics file path | |
| SERIALIZED_DIAGNOSTICS_FILE = "serialized_diagnostics_file", | |
| # Variable for the module file name. | |
| MODULE_NAME = "module_name", | |
| # Variable for the collection of include paths. | |
| INCLUDE_PATHS = "include_paths", | |
| # Variable for the collection of quote include paths. | |
| QUOTE_INCLUDE_PATHS = "quote_include_paths", | |
| # Variable for the collection of system include paths. | |
| SYSTEM_INCLUDE_PATHS = "system_include_paths", | |
| # Variable for the collection of external include paths. | |
| EXTERNAL_INCLUDE_PATHS = "external_include_paths", | |
| # Variable for the module map file name. | |
| MODULE_MAP_FILE = "module_map_file", | |
| # Variable for the dependent module map file name. | |
| DEPENDENT_MODULE_MAP_FILES = "dependent_module_map_files", | |
| # Variable for the collection of module files. | |
| MODULE_FILES = "module_files", | |
| # Variable for the collection of macros defined for preprocessor. */ | |
| PREPROCESSOR_DEFINES = "preprocessor_defines", | |
| # Variable for the gcov coverage file path. | |
| GCOV_GCNO_FILE = "gcov_gcno_file", | |
| # Variable for the minimized LTO indexing bitcode file, used by the LTO | |
| # indexing action. This file was generated by CppCompile actions. For | |
| # efficiency, it contains minimal information that is required by the LTO | |
| # indexing action. | |
| LTO_INDEXING_BITCODE_FILE = "lto_indexing_bitcode_file", | |
| # Variable for the LTO index file, used by the LTO backend action. This file | |
| # was generated by the LTO indexing action. | |
| THINLTO_INDEX = "thinlto_index", | |
| # Variable for the bitcode file that is input to LTO backend. | |
| THINLTO_INPUT_BITCODE_FILE = "thinlto_input_bitcode_file", | |
| # Variable for the object file that is output by LTO backend. | |
| THINLTO_OUTPUT_OBJECT_FILE = "thinlto_output_object_file", | |
| # Variable marking fission is used. | |
| IS_USING_FISSION = "is_using_fission", | |
| # Variable for the per object debug info file. | |
| PER_OBJECT_DEBUG_INFO_FILE = "per_object_debug_info_file", | |
| # Variable present when the output is compiled as position independent. | |
| PIC = "pic", | |
| # Variable marking memprof profile is being used | |
| IS_USING_MEMPROF = "is_using_memprof", | |
| # Variable for includes that compiler needs to include into sources. | |
| INCLUDES = "includes", | |
| ) | |
| # buildifier: disable=name-conventions | |
| _UnboundValueProviderDoNotUse = provider("This provider is used as an unique symbol to distinguish between bound and unbound Starlark values, to avoid using kwargs.", fields = []) | |
| _UNBOUND = _UnboundValueProviderDoNotUse() | |
| # IMPORTANT: This function is public API exposed on cc_common module! | |
| def create_compile_variables( | |
| *, | |
| cc_toolchain, | |
| feature_configuration, | |
| source_file = None, | |
| output_file = None, | |
| user_compile_flags = None, | |
| includes = None, | |
| local_includes = None, | |
| include_directories = None, | |
| quote_include_directories = None, | |
| system_include_directories = None, | |
| framework_include_directories = None, | |
| preprocessor_defines = None, | |
| thinlto_index = None, | |
| thinlto_input_bitcode_file = None, | |
| thinlto_output_object_file = None, | |
| use_pic = False, | |
| # TODO(b/65151735): Remove once we migrate crosstools to features | |
| add_legacy_cxx_options = False, # buildifier: disable=unused-variable | |
| variables_extension = {}, | |
| strip_opts = _UNBOUND, | |
| input_file = _UNBOUND): | |
| """Returns variables used for compilation actions. | |
| Args: | |
| cc_toolchain: cc_toolchain for which we are creating build variables. | |
| feature_configuration: Feature configuration to be queried. | |
| source_file: Optional source file path for the compilation. Please prefer passing source_file | |
| here over appending it to the end of the command line generated from | |
| cc_common.get_memory_inefficient_command_line, as then it's in the power of | |
| the toolchain author to properly specify and position compiler flags. | |
| output_file: Optional output file path of the compilation. Please prefer passing output_file | |
| here over appending it to the end of the command line generated from | |
| cc_common.get_memory_inefficient_command_line, as then it's in the power of | |
| the toolchain author to properly specify and position compiler flags. | |
| includes: paths to headers that should be included using -include | |
| user_compile_flags: List of additional compilation flags (copts). | |
| include_directories: Depset of include directories. | |
| local_includes: Depset of local include directories. | |
| quote_include_directories: Depset of quote include directories. | |
| system_include_directories: Depset of system include directories. | |
| framework_include_directories: Depset of framework include directories. | |
| preprocessor_defines: Depset of preprocessor defines. | |
| thinlto_index: LTO index file path. | |
| thinlto_input_bitcode_file: Bitcode file that is input to LTO backend. | |
| thinlto_output_object_file: Object file that is output by LTO backend. | |
| use_pic: When true the compilation will generate position independent code. | |
| add_legacy_cxx_options: Unused. | |
| variables_extension: A dictionary of additional variables used by compile actions. | |
| strip_opts: (Private API) | |
| input_file: (Private API) | |
| Returns: | |
| (CcToolchainVariables) common compile build variables | |
| """ | |
| if strip_opts != _UNBOUND or input_file != _UNBOUND: | |
| _cc_internal.check_private_api(allowlist = _PRIVATE_STARLARKIFICATION_ALLOWLIST) | |
| if strip_opts == _UNBOUND: | |
| strip_opts = [] | |
| if input_file == _UNBOUND: | |
| input_file = None | |
| if (use_pic and not feature_configuration.is_enabled("pic") and not feature_configuration.is_enabled("supports_pic")): | |
| fail("PIC compilation is requested but the toolchain does not support it " + | |
| "(feature named 'supports_pic' is not enabled)") | |
| cpp_configuration = cc_toolchain._cpp_configuration | |
| fdo_context = cc_toolchain._fdo_context | |
| common_vars = _setup_common_compile_build_variables_internal( | |
| feature_configuration = feature_configuration, | |
| is_using_memprof = getattr(fdo_context, "memprof_profile_artifact", None) != None, | |
| fdo_build_stamp = get_fdo_build_stamp(cpp_configuration, fdo_context, feature_configuration), | |
| variables_extension = variables_extension, | |
| includes = includes or [], | |
| local_includes = local_includes or depset(), | |
| include_dirs = include_directories or depset(), | |
| quote_include_dirs = quote_include_directories or depset(), | |
| system_include_dirs = system_include_directories or depset(), | |
| framework_include_dirs = framework_include_directories or depset(), | |
| defines = preprocessor_defines or depset(), | |
| ) | |
| additional_build_variables = {} | |
| additional_build_variables["stripopts"] = strip_opts | |
| if input_file: | |
| additional_build_variables["input_file"] = input_file | |
| variables = get_specific_compile_build_variables( | |
| use_pic = use_pic, | |
| source_file = source_file, | |
| output_file = output_file, | |
| thinlto_index = thinlto_index, | |
| thinlto_bitcode_file = thinlto_input_bitcode_file, | |
| thinlto_output_object_file = thinlto_output_object_file, | |
| additional_build_variables = additional_build_variables, | |
| user_compile_flags = user_compile_flags or [], | |
| ) | |
| return _cc_internal.combine_cc_toolchain_variables(cc_toolchain._build_variables, common_vars, variables) | |
| # buildifier: disable=function-docstring | |
| def setup_common_compile_build_variables( | |
| *, | |
| cc_compilation_context, | |
| cc_toolchain, | |
| cpp_configuration, | |
| fdo_context, | |
| feature_configuration, | |
| variables_extension): | |
| common_vars = _setup_common_compile_build_variables_internal( | |
| feature_configuration = feature_configuration, | |
| is_using_memprof = getattr(fdo_context, "memprof_profile_artifact", None) != None, | |
| fdo_build_stamp = get_fdo_build_stamp(cpp_configuration, fdo_context, feature_configuration), | |
| variables_extension = variables_extension, | |
| include_dirs = cc_compilation_context.includes, | |
| local_includes = cc_compilation_context.local_includes or depset(), | |
| quote_include_dirs = cc_compilation_context.quote_includes, | |
| system_include_dirs = cc_compilation_context.system_includes, | |
| framework_include_dirs = cc_compilation_context.framework_includes, | |
| defines = cc_compilation_context.defines, | |
| local_defines = cc_compilation_context.local_defines, | |
| external_include_dirs = cc_compilation_context.external_includes, | |
| cpp_module_map = cc_compilation_context._module_map if feature_configuration.is_enabled("module_maps") else None, | |
| direct_module_maps = cc_compilation_context._direct_module_maps, | |
| ) | |
| return _cc_internal.combine_cc_toolchain_variables(cc_toolchain._build_variables, common_vars) | |
| def _setup_common_compile_build_variables_internal( | |
| *, | |
| feature_configuration, | |
| fdo_build_stamp, # str | |
| is_using_memprof, # bool | |
| includes = [], # [str] | |
| variables_extension = [], # [dict{str,object}] | |
| additional_build_variables = {}, # dict{str,str} | |
| include_dirs = depset(), | |
| local_includes = depset(), | |
| quote_include_dirs = depset(), | |
| system_include_dirs = depset(), | |
| framework_include_dirs = depset(), | |
| defines = depset(), | |
| local_defines = depset(), | |
| external_include_dirs = depset(), | |
| cpp_module_map = None, | |
| direct_module_maps = depset()): | |
| result = {} | |
| if cpp_module_map: | |
| result[_VARS.MODULE_NAME] = get_module_map_name(cpp_module_map) | |
| result[_VARS.MODULE_MAP_FILE] = cpp_module_map.file | |
| result[_VARS.DEPENDENT_MODULE_MAP_FILES] = direct_module_maps | |
| if feature_configuration.is_enabled("use_header_modules"): | |
| result[_VARS.MODULE_FILES] = () | |
| if feature_configuration.is_requested("system_include_paths"): | |
| result[_VARS.INCLUDE_PATHS] = include_dirs | |
| result[_VARS.SYSTEM_INCLUDE_PATHS] = depset(transitive = [system_include_dirs, local_includes]) | |
| else: | |
| result[_VARS.INCLUDE_PATHS] = depset(transitive = [include_dirs, local_includes]) | |
| result[_VARS.SYSTEM_INCLUDE_PATHS] = system_include_dirs | |
| result[_VARS.QUOTE_INCLUDE_PATHS] = quote_include_dirs | |
| if includes: | |
| result[_VARS.INCLUDES] = _cc_internal.intern_string_sequence_variable_value(includes) | |
| result[_VARS.FRAMEWORK_PATHS] = framework_include_dirs | |
| if is_using_memprof: | |
| result[_VARS.IS_USING_MEMPROF] = "1" | |
| # Stamp FDO builds with FDO subtype string | |
| all_defines = defines.to_list() + local_defines.to_list() + ( | |
| ["BUILD_FDO_TYPE=\"" + fdo_build_stamp + "\""] if fdo_build_stamp else [] | |
| ) | |
| result[_VARS.PREPROCESSOR_DEFINES] = _cc_internal.intern_string_sequence_variable_value(all_defines) | |
| result = result | additional_build_variables | |
| for key, value in variables_extension.items(): | |
| if type(value) == type([]): | |
| result[key] = _cc_internal.intern_string_sequence_variable_value(value) | |
| elif type(value) == type(""): | |
| result[key] = value | |
| elif type(value) == type(depset()): | |
| for e in value.to_list(): | |
| if type(e) != type(""): | |
| fail("for string_sequence_variables_extension, got element of type " + type(e) + ", want string") | |
| result[key] = value | |
| else: | |
| fail("for variable extension key:" + key + ", got element of type " + type(value) + ", want string") | |
| if external_include_dirs: | |
| result[_VARS.EXTERNAL_INCLUDE_PATHS] = external_include_dirs | |
| return _cc_internal.cc_toolchain_variables(vars = result) | |
| # Note: this method is side-effect free, callers should add fdo inputs to | |
| # cc_compile_action_builder themselves | |
| def get_specific_compile_build_variables( | |
| use_pic, | |
| source_file = None, | |
| output_file = None, | |
| dotd_file = None, | |
| diagnostics_file = None, | |
| gcno_file = None, | |
| dwo_file = None, | |
| lto_indexing_file = None, | |
| thinlto_index = None, | |
| thinlto_bitcode_file = None, | |
| thinlto_output_object_file = None, | |
| using_fission = False, | |
| code_coverage_enabled = False, | |
| module_name = None, | |
| user_compile_flags = [], | |
| additional_build_variables = {}, | |
| fdo_build_variables = {}): | |
| """Creates a CcToolchainVariables instance | |
| Args: | |
| use_pic: (bool) | |
| source_file: (File) | |
| output_file: (File) | |
| dotd_file: (File) | |
| diagnostics_file: (File) | |
| gcno_file: (File) | |
| dwo_file: (File) | |
| lto_indexing_file: (File) | |
| thinlto_index: (File) | |
| thinlto_bitcode_file: (File) | |
| thinlto_output_object_file: (File) | |
| using_fission: (bool) | |
| code_coverage_enabled: (bool) | |
| module_name: (str) Overrides the module name set by | |
| setup_common_compile_build_variables. | |
| user_compile_flags: (list[str]) | |
| additional_build_variables: (dict{str,str}) | |
| fdo_build_variables: (dict{str,str}) | |
| Returns: | |
| (Variables) | |
| """ | |
| result = {} | |
| if module_name: | |
| result[_VARS.MODULE_NAME] = module_name | |
| result[_VARS.USER_COMPILE_FLAGS] = _cc_internal.intern_string_sequence_variable_value(user_compile_flags) | |
| if source_file: | |
| result[_VARS.SOURCE_FILE] = source_file | |
| if output_file: | |
| result[_VARS.OUTPUT_FILE] = output_file | |
| # Set dependency_file to enable <object>.d file generation. | |
| if dotd_file: | |
| result[_VARS.DEPENDENCY_FILE] = dotd_file | |
| # Set diagnostics_file to enable <object>.dia file generation. | |
| if diagnostics_file: | |
| result[_VARS.SERIALIZED_DIAGNOSTICS_FILE] = diagnostics_file | |
| if gcno_file: | |
| result[_VARS.GCOV_GCNO_FILE] = gcno_file | |
| elif code_coverage_enabled: | |
| # TODO: Blaze currently uses `gcov_gcno_file` to detect if code coverage | |
| # is enabled. It should use a different signal. | |
| result[_VARS.GCOV_GCNO_FILE] = "" | |
| if dwo_file: | |
| result[_VARS.PER_OBJECT_DEBUG_INFO_FILE] = dwo_file | |
| if using_fission: | |
| result[_VARS.IS_USING_FISSION] = "" | |
| if lto_indexing_file: | |
| result[_VARS.LTO_INDEXING_BITCODE_FILE] = lto_indexing_file | |
| if thinlto_index: | |
| result[_VARS.THINLTO_INDEX] = thinlto_index | |
| if thinlto_bitcode_file: | |
| result[_VARS.THINLTO_INPUT_BITCODE_FILE] = thinlto_bitcode_file | |
| if thinlto_output_object_file: | |
| result[_VARS.THINLTO_OUTPUT_OBJECT_FILE] = thinlto_output_object_file | |
| if use_pic: | |
| result[_VARS.PIC] = "" | |
| result = result | additional_build_variables | |
| result = result | fdo_build_variables | |
| return _cc_internal.cc_toolchain_variables(vars = result) | |
| _SOURCE_TYPES_FOR_CXXOPTS = set( | |
| extensions.CC_SOURCE + | |
| extensions.CC_HEADER + | |
| extensions.CLIF_INPUT_PROTO + | |
| extensions.CPP_MODULE_MAP + | |
| extensions.OBJCPP_SOURCE, | |
| ) | |
| # buildifier: disable=function-docstring | |
| def get_copts( | |
| language, | |
| cpp_configuration, | |
| source_file, | |
| conlyopts, | |
| copts, | |
| cxxopts, | |
| label, | |
| override_extension = None): | |
| if override_extension != None: | |
| extension = override_extension | |
| elif source_file.extension: | |
| extension = "." + source_file.extension | |
| else: | |
| extension = "" | |
| result = [] | |
| result.extend(_copts_from_options(language, cpp_configuration, extension)) | |
| result.extend(copts) | |
| if extension in extensions.C_SOURCE: | |
| result.extend(conlyopts) | |
| if extension in _SOURCE_TYPES_FOR_CXXOPTS: | |
| result.extend(cxxopts) | |
| if label: | |
| result.extend(_cc_internal.per_file_copts(cpp_configuration, source_file, label)) | |
| return result | |
| def _copts_from_options(language, cpp_configuration, extension): | |
| result = [] | |
| result.extend(cpp_configuration.copts) | |
| if extension in extensions.C_SOURCE: | |
| result.extend(cpp_configuration.conlyopts) | |
| if extension in _SOURCE_TYPES_FOR_CXXOPTS: | |
| result.extend(cpp_configuration.cxxopts) | |
| if extension in extensions.OBJC_SOURCE or extension in extensions.OBJCPP_SOURCE or ( | |
| language == "objc" and extension in extensions.CC_HEADER | |
| ): | |
| result.extend(cpp_configuration.objccopts) | |
| return result | |
| def get_fdo_variables_and_inputs( | |
| cc_toolchain, | |
| fdo_context, | |
| feature_configuration, | |
| cpp_configuration): | |
| auxiliary_fdo_inputs_list = _get_auxiliary_fdo_inputs_list( | |
| cc_toolchain = cc_toolchain, | |
| fdo_context = fdo_context, | |
| feature_configuration = feature_configuration, | |
| ) | |
| fdo_build_variables = _setup_fdo_build_variables( | |
| cc_toolchain = cc_toolchain, | |
| fdo_context = fdo_context, | |
| auxiliary_fdo_inputs_list = auxiliary_fdo_inputs_list, | |
| feature_configuration = feature_configuration, | |
| fdo_instrument = cpp_configuration.fdo_instrument(), | |
| cs_fdo_instrument = cpp_configuration.cs_fdo_instrument(), | |
| ) | |
| # TODO(b/396122076): once starlarkification of CcStaticCompilationHelper is done, check whether | |
| # we can change auxiliary_fdo_inputs from depset to list. | |
| auxiliary_fdo_inputs = depset(direct = auxiliary_fdo_inputs_list) | |
| return fdo_build_variables, auxiliary_fdo_inputs | |
| def _setup_fdo_build_variables( | |
| cc_toolchain, | |
| fdo_context, | |
| auxiliary_fdo_inputs_list, | |
| feature_configuration, | |
| fdo_instrument, | |
| cs_fdo_instrument): | |
| """Populates FDO build variables.""" | |
| variables = {} | |
| if feature_configuration.is_enabled("fdo_instrument"): | |
| variables["fdo_instrument_path"] = fdo_instrument | |
| if feature_configuration.is_enabled("cs_fdo_instrument"): | |
| variables["cs_fdo_instrument_path"] = cs_fdo_instrument | |
| if not (getattr(fdo_context, "branch_fdo_profile", None) or | |
| getattr(fdo_context, "prefetch_hints_artifact", None) or | |
| getattr(fdo_context, "propeller_optimize_info", None) or | |
| getattr(fdo_context, "memprof_profile_artifact", None)): | |
| return variables | |
| prefetch_hints_artifact = getattr(fdo_context, "prefetch_hints_artifact", None) | |
| if prefetch_hints_artifact: | |
| variables["fdo_prefetch_hints_path"] = prefetch_hints_artifact.path | |
| if _should_pass_propeller_profiles(cc_toolchain, fdo_context, feature_configuration): | |
| # _should_pass_propeller_profiles() ensures that fdo_context.propeller_optimize_info | |
| # is not None. | |
| cc_artifact = getattr(fdo_context.propeller_optimize_info, "cc_profile", None) | |
| if cc_artifact: | |
| variables["propeller_optimize_cc_path"] = cc_artifact.path | |
| ld_artifact = getattr(fdo_context.propeller_optimize_info, "ld_profile", None) | |
| if ld_artifact: | |
| variables["propeller_optimize_ld_path"] = ld_artifact.path | |
| memprof_profile_artifact = getattr(fdo_context, "memprof_profile_artifact", None) | |
| if memprof_profile_artifact: | |
| variables["memprof_profile_path"] = memprof_profile_artifact.path | |
| branch_fdo_profile = getattr(fdo_context, "branch_fdo_profile", None) | |
| if (branch_fdo_profile and | |
| auxiliary_fdo_inputs_list and | |
| ( | |
| feature_configuration.is_enabled("autofdo") or | |
| feature_configuration.is_enabled("xbinaryfdo") or | |
| ( | |
| feature_configuration.is_enabled("fdo_optimize") and | |
| branch_fdo_profile.branch_fdo_mode in ("llvm_fdo", "llvm_cs_fdo") | |
| ) | |
| )): | |
| variables["fdo_profile_path"] = branch_fdo_profile.profile_artifact.path | |
| return variables | |
| def _get_auxiliary_fdo_inputs_list( | |
| cc_toolchain, | |
| fdo_context, | |
| feature_configuration): | |
| """Returns the auxiliary files that need to be added to CppCompileAction.""" | |
| auxiliary_inputs = [] | |
| prefetch_hints_artifact = getattr(fdo_context, "prefetch_hints_artifact", None) | |
| if prefetch_hints_artifact: | |
| auxiliary_inputs.append(prefetch_hints_artifact) | |
| if _should_pass_propeller_profiles(cc_toolchain, fdo_context, feature_configuration): | |
| # _should_pass_propeller_profiles() ensures that fdo_context.propeller_optimize_info | |
| # is not None. | |
| cc_artifact = getattr(fdo_context.propeller_optimize_info, "cc_profile", None) | |
| if cc_artifact: | |
| auxiliary_inputs.append(cc_artifact) | |
| ld_artifact = getattr(fdo_context.propeller_optimize_info, "ld_profile", None) | |
| if ld_artifact: | |
| auxiliary_inputs.append(ld_artifact) | |
| memprof_profile_artifact = getattr(fdo_context, "memprof_profile_artifact", None) | |
| if memprof_profile_artifact: | |
| auxiliary_inputs.append(memprof_profile_artifact) | |
| branch_fdo_profile = getattr(fdo_context, "branch_fdo_profile", None) | |
| # If --fdo_optimize was not specified, we don't have any additional inputs. | |
| if branch_fdo_profile: | |
| auxiliary_inputs.append(branch_fdo_profile.profile_artifact) | |
| return auxiliary_inputs | |
| def _should_pass_propeller_profiles( | |
| cc_toolchain, | |
| fdo_context, | |
| feature_configuration): | |
| """Returns whether Propeller profiles should be passed to a compile action.""" | |
| if cc_toolchain._is_tool_configuration: | |
| # Propeller doesn't make much sense for host builds. | |
| return False | |
| if getattr(fdo_context, "propeller_optimize_info", None) == None: | |
| # No Propeller profiles to pass. | |
| return False | |
| # Don't pass Propeller input files if they have no effect (i.e. for ThinLTO). | |
| return (not feature_configuration.is_enabled("thin_lto") or | |
| feature_configuration.is_enabled("propeller_optimize_thinlto_compile_actions")) | |
| def get_linkstamp_compile_variables( | |
| source_file, | |
| output_file, | |
| target_name, | |
| build_target, | |
| additional_linkstamp_defines, | |
| build_info_header_artifacts, | |
| feature_configuration, | |
| cc_toolchain, | |
| needs_pic): | |
| """Returns variables for linkstamp compilation. | |
| Args: | |
| source_file: The linkstamp source file to be compiled. | |
| output_file: The output object file. | |
| target_name: Value for the G3_TARGET_NAME linkstamp define. | |
| build_target: Value for the G3_BUILD_TARGET linkstamp define. | |
| additional_linkstamp_defines: A list of additional defines for linkstamp compilation. | |
| build_info_header_artifacts: A list of build info header artifacts. | |
| feature_configuration: The feature configuration. | |
| cc_toolchain: The C++ toolchain provider. | |
| needs_pic: Whether PIC compilation is needed. | |
| Returns: | |
| CcToolchainVariables for linkstamp compilation. | |
| """ | |
| if not _cc_common_internal.action_is_enabled( | |
| feature_configuration = feature_configuration, | |
| action_name = "linkstamp-compile", | |
| ): | |
| fail("Action 'linkstamp-compile' is not configured.") | |
| copts = get_copts( | |
| language = "c++", # The only language that receives special treatment is "objc". | |
| cpp_configuration = cc_toolchain._cpp_configuration, | |
| source_file = source_file, | |
| conlyopts = [], | |
| copts = [], | |
| cxxopts = [], | |
| label = None, | |
| ) | |
| defines = _compute_all_linkstamp_defines( | |
| target_name = target_name, | |
| build_target = build_target, | |
| additional_linkstamp_defines = additional_linkstamp_defines, | |
| cc_toolchain = cc_toolchain, | |
| feature_configuration = feature_configuration, | |
| ) | |
| return create_compile_variables( | |
| feature_configuration = feature_configuration, | |
| cc_toolchain = cc_toolchain, | |
| source_file = source_file, | |
| output_file = output_file, | |
| use_pic = needs_pic, | |
| preprocessor_defines = depset(defines), | |
| includes = [a.path for a in build_info_header_artifacts], | |
| include_directories = depset(["."]), | |
| user_compile_flags = copts, | |
| ) | |
| def _stamps_to_defines(stamps): | |
| """Converts a dictionary of stamps to a list of C preprocessor defines.""" | |
| defines = [] | |
| for k, v in stamps.items(): | |
| if v.isdigit() or k == "BUILD_LTO_TYPE": | |
| # BUILD_LTO_TYPE is a special case because of the AS_STRING(x) call in "builddata_globals.cc". | |
| # Normally, a string set as -DKEY_NAME="VALUE" is interpreted as KEY_NAME="VALUE", | |
| # but for this specific case, it's KEY_NAME="\"VALUE\"" because of AS_STRING(x). | |
| defines.append("{}={}".format(k, v)) | |
| else: | |
| defines.append('{}="{}"'.format(k, v)) | |
| return defines | |
| def _compute_all_linkstamp_defines( | |
| target_name, | |
| build_target, | |
| additional_linkstamp_defines, | |
| cc_toolchain, | |
| feature_configuration): | |
| """Computes defines for linkstamp compilation.""" | |
| stamps = get_linkstamp_stamps( | |
| cc_toolchain = cc_toolchain, | |
| feature_configuration = feature_configuration, | |
| target_name = target_name, | |
| build_target = build_target, | |
| additional_linkstamp_defines = additional_linkstamp_defines, | |
| ) | |
| return _stamps_to_defines(stamps) | |
| COMPILE_BUILD_VARIABLES = _VARS |