blob: 95f500c617b55701570ad9a6fc9c2e5633e5ebad [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.
"""
The CcCompilationOutputs provider.
"""
load("//cc/common:cc_helper_internal.bzl", "wrap_with_check_private_api", _PRIVATE_STARLARKIFICATION_ALLOWLIST = "PRIVATE_STARLARKIFICATION_ALLOWLIST")
load("//cc/private:cc_internal.bzl", _cc_internal = "cc_internal")
load("//cc/private/compile:lto_compilation_context.bzl", "EMPTY_LTO_COMPILATION_CONTEXT", "merge_lto_compilation_contexts")
# 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()
CcCompilationOutputsInfo = provider(
doc = "The outputs of a C++ compilation.",
fields = {
"objects": "(list[File]) All .o files built by the target.",
"pic_objects": "(list[File]) All .pic.o files built by the target.",
"_lto_compilation_context": "(LTOCompilationContext) Maps all .o bitcode files coming from a ThinLTO C(++) compilation under our control toinformation needed by the LTO indexing and backend steps.",
"_dwo_files": "(list[File]) All .dwo files built by the target, corresponding to .o outputs.",
"_pic_dwo_files": "(list[File]) All .pic.dwo files built by the target, corresponding to .pic.o outputs.",
"_gcno_files": "(list[File]) All .gcno files built by the target, corresponding to .o outputs.",
"_pic_gcno_files": "(list[File]) All .pic.gcno files built by the target, corresponding to .pic.gcno outputs.",
"temps": '(() -> depset[File]) All artifacts that are created if "--save_temps" is true.',
"_header_tokens": "(list[File]) All token .h.processed files created when preprocessing or parsing headers.",
"_module_files": "(list[File]) All .pcm files built by the target.",
"cpp_module_files": "(list[File]) All .pcm files built by the target's C++20 Modules interface.",
"pic_cpp_module_files": "(list[File]) All .pic.pcm files built by the target's C++20 Modules interface.",
"cpp_modules_info_file": "(File) .CXXModules.json file created by the target.",
"pic_cpp_modules_info_file": "(File) .CXXModules.json file created by the target.",
},
)
def create_compilation_outputs_internal(
*,
objects = [],
pic_objects = [],
lto_compilation_context = None,
dwo_files = [],
pic_dwo_files = [],
gcno_files = [],
pic_gcno_files = [],
temps = [],
header_tokens = [],
module_files = [],
cpp_module_files = [],
pic_cpp_module_files = [],
cpp_modules_info_file = None,
pic_cpp_modules_info_file = None):
"""Creates a CcCompilationOutputsInfo provider.
Args:
objects: A list of object files.
pic_objects: A list of PIC object files.
lto_compilation_context: The LTO compilation context.
dwo_files: A list of dwo files.
pic_dwo_files: A list of PIC dwo files.
gcno_files: A list of gcno files.
pic_gcno_files: A list of PIC gcno files.
temps: A depset of temporary files.
header_tokens: A list of header tokens.
module_files: A list of module files.
cpp_module_files: A list of C++ module files.
pic_cpp_module_files: A list of PIC C++ module files.
cpp_modules_info_file: A C++ modules info file.
pic_cpp_modules_info_file: A PIC C++ modules info file.
Returns:
A CcCompilationOutputsInfo provider.
"""
if lto_compilation_context == None:
lto_compilation_context = EMPTY_LTO_COMPILATION_CONTEXT
return CcCompilationOutputsInfo(
objects = _cc_internal.freeze(objects),
pic_objects = _cc_internal.freeze(pic_objects),
temps = wrap_with_check_private_api(depset(temps)),
_header_tokens = _cc_internal.freeze(header_tokens),
_module_files = _cc_internal.freeze(module_files),
_lto_compilation_context = lto_compilation_context,
_gcno_files = _cc_internal.freeze(gcno_files),
_pic_gcno_files = _cc_internal.freeze(pic_gcno_files),
_dwo_files = _cc_internal.freeze(dwo_files),
_pic_dwo_files = _cc_internal.freeze(pic_dwo_files),
cpp_module_files = _cc_internal.freeze(cpp_module_files),
pic_cpp_module_files = _cc_internal.freeze(pic_cpp_module_files),
cpp_modules_info_file = cpp_modules_info_file,
pic_cpp_modules_info_file = pic_cpp_modules_info_file,
)
EMPTY_COMPILATION_OUTPUTS = create_compilation_outputs_internal()
def _validate_extensions(param_name, files, valid_extensions):
"""Validates that the files have the correct extensions.
Args:
param_name: The name of the parameter being validated.
files: A list of files to validate.
valid_extensions: A list of valid extensions.
"""
for file in files:
if type(file) != "File":
fail("for '%s', got a depset of '%s', expected a depset of 'File'" % (param_name, type(file)))
if file.is_directory:
continue
if file.extension not in valid_extensions:
fail(
"'%s' has wrong extension. The list of possible extensions for '%s' is: %s" % (
file.path,
param_name,
", ".join(valid_extensions),
),
)
def _to_list(data):
if not data:
return []
if type(data) == type(depset()):
return data.to_list()
if type(data) == type([]):
return data
fail("Expected depset or list for artifacts, got " + type(data))
# IMPORTANT: This function is public API exposed on cc_common module!
def create_compilation_outputs(
*,
objects = None,
pic_objects = None,
lto_compilation_context = _UNBOUND,
dwo_objects = _UNBOUND,
pic_dwo_objects = _UNBOUND):
"""Creates a CcCompilationOutputsInfo provider from Starlark.
Args:
objects: A depset or list of object files.
pic_objects: A depset or list of PIC object files.
lto_compilation_context: The LTO compilation context.
dwo_objects: A depset or list of dwo files.
pic_dwo_objects: A depset or list of PIC dwo files.
Returns:
A CcCompilationOutputsInfo provider.
"""
if lto_compilation_context != _UNBOUND or dwo_objects != _UNBOUND or pic_dwo_objects != _UNBOUND:
_cc_internal.check_private_api(allowlist = _PRIVATE_STARLARKIFICATION_ALLOWLIST)
if lto_compilation_context == _UNBOUND:
lto_compilation_context = None
if dwo_objects == _UNBOUND:
dwo_objects = []
if pic_dwo_objects == _UNBOUND:
pic_dwo_objects = []
objects = _to_list(objects)
pic_objects = _to_list(pic_objects)
dwo_objects = _to_list(dwo_objects)
pic_dwo_objects = _to_list(pic_dwo_objects)
obj_extensions = ["o", "obj", "opb", "bc"]
_validate_extensions("objects", objects, obj_extensions)
_validate_extensions("pic_objects", pic_objects, obj_extensions)
return create_compilation_outputs_internal(
objects = objects,
pic_objects = pic_objects,
lto_compilation_context = lto_compilation_context,
dwo_files = dwo_objects,
pic_dwo_files = pic_dwo_objects,
)
# IMPORTANT: This function is public API exposed on cc_common module!
def merge_compilation_outputs(*, compilation_outputs):
"""Merges a list of CcCompilationOutputsInfo providers.
Args:
compilation_outputs: A list of CcCompilationOutputsInfo providers.
Returns:
A CcCompilationOutputsInfo provider.
"""
objects = []
pic_objects = []
dwo_files = []
pic_dwo_files = []
gcno_files = []
pic_gcno_files = []
lto_compilation_contexts = []
transitive_temps = []
header_tokens = []
module_files = []
for co in compilation_outputs:
objects.extend(co.objects)
pic_objects.extend(co.pic_objects)
dwo_files.extend(co._dwo_files)
pic_dwo_files.extend(co._pic_dwo_files)
gcno_files.extend(co._gcno_files)
pic_gcno_files.extend(co._pic_gcno_files)
transitive_temps.append(co.temps())
header_tokens.extend(co._header_tokens)
module_files.extend(co._module_files)
if co._lto_compilation_context:
lto_compilation_contexts.append(co._lto_compilation_context)
return CcCompilationOutputsInfo(
objects = objects,
pic_objects = pic_objects,
_lto_compilation_context = merge_lto_compilation_contexts(lto_compilation_contexts = lto_compilation_contexts),
_dwo_files = dwo_files,
_pic_dwo_files = pic_dwo_files,
_gcno_files = gcno_files,
_pic_gcno_files = pic_gcno_files,
temps = wrap_with_check_private_api(depset(transitive = transitive_temps)),
_header_tokens = header_tokens,
_module_files = module_files,
)