mirror of
https://github.com/bazelbuild/rules_cc
synced 2024-11-27 20:43:26 +00:00
Add strictly typed variables toolchain rules.
BEGIN_PUBLIC Add strictly typed variables to toolchain rules. This should allow us to implement a proper replacement for flag_group END_PUBLIC PiperOrigin-RevId: 617338607 Change-Id: I7f3058578cb5eb17ecc1aa38d2e1459e0742aee9
This commit is contained in:
parent
aa19278bbd
commit
17143d150d
|
@ -45,6 +45,23 @@ ActionTypeSetInfo = provider(
|
|||
},
|
||||
)
|
||||
|
||||
VariableInfo = provider(
|
||||
"""A variable defined by the toolchain""",
|
||||
# @unsorted-dict-items
|
||||
fields = {
|
||||
"name": "(str) The variable name",
|
||||
"actions": "(Optional[depset[ActionTypeInfo]]) The actions this variable is available for",
|
||||
"type": "A type constructed using variables.types.*",
|
||||
},
|
||||
)
|
||||
|
||||
BuiltinVariablesInfo = provider(
|
||||
doc = "The builtin variables",
|
||||
fields = {
|
||||
"variables": "(dict[str, struct(type=type, actions=Optional[depset[ActionTypeInfo]]) A mapping from variable name to variable metadata.",
|
||||
},
|
||||
)
|
||||
|
||||
NestedArgsInfo = provider(
|
||||
doc = "A provider representation of Args.add/add_all/add_joined parameters",
|
||||
# @unsorted-dict-items
|
||||
|
|
171
cc/toolchains/impl/variables.bzl
Normal file
171
cc/toolchains/impl/variables.bzl
Normal file
|
@ -0,0 +1,171 @@
|
|||
# Copyright 2024 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.
|
||||
"""Rules for accessing cc build variables in bazel toolchains safely."""
|
||||
|
||||
load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeSetInfo", "BuiltinVariablesInfo", "VariableInfo")
|
||||
load(":collect.bzl", "collect_action_types", "collect_provider")
|
||||
|
||||
visibility([
|
||||
"//cc/toolchains/variables",
|
||||
"//tests/rule_based_toolchain/...",
|
||||
])
|
||||
|
||||
types = struct(
|
||||
unknown = dict(name = "unknown", repr = "unknown"),
|
||||
void = dict(name = "void", repr = "void"),
|
||||
string = dict(name = "string", repr = "string"),
|
||||
bool = dict(name = "bool", repr = "bool"),
|
||||
# File and directory are basically the same thing as string for now.
|
||||
file = dict(name = "file", repr = "File"),
|
||||
directory = dict(name = "directory", repr = "directory"),
|
||||
option = lambda element: dict(
|
||||
name = "option",
|
||||
elements = element,
|
||||
repr = "Option[%s]" % element["repr"],
|
||||
),
|
||||
list = lambda elements: dict(
|
||||
name = "list",
|
||||
elements = elements,
|
||||
repr = "List[%s]" % elements["repr"],
|
||||
),
|
||||
struct = lambda **kv: dict(
|
||||
name = "struct",
|
||||
kv = kv,
|
||||
repr = "struct(%s)" % ", ".join([
|
||||
"{k}={v}".format(k = k, v = v["repr"])
|
||||
for k, v in sorted(kv.items())
|
||||
]),
|
||||
),
|
||||
)
|
||||
|
||||
def _cc_variable_impl(ctx):
|
||||
return [VariableInfo(
|
||||
name = ctx.label.name,
|
||||
type = json.decode(ctx.attr.type),
|
||||
actions = collect_action_types(ctx.attr.actions) if ctx.attr.actions else None,
|
||||
)]
|
||||
|
||||
_cc_variable = rule(
|
||||
implementation = _cc_variable_impl,
|
||||
attrs = {
|
||||
"actions": attr.label_list(providers = [ActionTypeSetInfo]),
|
||||
"type": attr.string(mandatory = True),
|
||||
},
|
||||
provides = [VariableInfo],
|
||||
)
|
||||
|
||||
def cc_variable(name, type, **kwargs):
|
||||
"""Defines a variable for both the specified variable, and all nested ones.
|
||||
|
||||
Eg. cc_variable(
|
||||
name = "foo",
|
||||
type = types.list(types.struct(bar = types.string))
|
||||
)
|
||||
|
||||
would define two targets, ":foo" and ":foo.bar"
|
||||
|
||||
Args:
|
||||
name: (str) The name of the outer variable, and the rule.
|
||||
type: The type of the variable, constructed using types above.
|
||||
**kwargs: kwargs to pass to _cc_variable.
|
||||
"""
|
||||
_cc_variable(name = name, type = json.encode(type), **kwargs)
|
||||
|
||||
def _cc_builtin_variables_impl(ctx):
|
||||
return [BuiltinVariablesInfo(variables = {
|
||||
variable.name: struct(
|
||||
actions = variable.actions,
|
||||
type = variable.type,
|
||||
)
|
||||
for variable in collect_provider(ctx.attr.srcs, VariableInfo)
|
||||
})]
|
||||
|
||||
cc_builtin_variables = rule(
|
||||
implementation = _cc_builtin_variables_impl,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(providers = [VariableInfo]),
|
||||
},
|
||||
)
|
||||
|
||||
def get_type(*, name, variables, overrides, actions, args_label, nested_label, fail):
|
||||
"""Gets the type of a variable.
|
||||
|
||||
Args:
|
||||
name: (str) The variable to look up.
|
||||
variables: (dict[str, VariableInfo]) Mapping from variable name to
|
||||
metadata. Top-level variables only
|
||||
overrides: (dict[str, type]) Mapping from variable names to type.
|
||||
Can be used for nested variables.
|
||||
actions: (depset[ActionTypeInfo]) The set of actions for which the
|
||||
variable is requested.
|
||||
args_label: (Label) The label for the args that included the rule that
|
||||
references this variable. Only used for error messages.
|
||||
nested_label: (Label) The label for the rule that references this
|
||||
variable. Only used for error messages.
|
||||
fail: A function to be called upon failure. Use for testing only.
|
||||
Returns:
|
||||
The type of the variable "name".
|
||||
"""
|
||||
outer = name.split(".")[0]
|
||||
if outer not in variables:
|
||||
# With a fail function, we actually need to return since the fail
|
||||
# function doesn't propagate.
|
||||
fail("The variable %s does not exist. Did you mean one of the following?\n%s" % (outer, "\n".join(sorted(variables))))
|
||||
|
||||
# buildifier: disable=unreachable
|
||||
return types.void
|
||||
|
||||
if variables[outer].actions != None:
|
||||
valid_actions = variables[outer].actions.to_list()
|
||||
for action in actions:
|
||||
if action not in valid_actions:
|
||||
fail("The variable {var} is inaccessible from the action {action}. This is required because it is referenced in {nested_label}, which is included by {args_label}, which references that action".format(
|
||||
var = outer,
|
||||
nested_label = nested_label,
|
||||
args_label = args_label,
|
||||
action = action.label,
|
||||
))
|
||||
|
||||
# buildifier: disable=unreachable
|
||||
return types.void
|
||||
|
||||
type = overrides.get(outer, variables[outer].type)
|
||||
|
||||
parent = outer
|
||||
for part in name.split(".")[1:]:
|
||||
full = parent + "." + part
|
||||
|
||||
if type["name"] != "struct":
|
||||
extra_error = ""
|
||||
if type["name"] == "list" and type["elements"]["name"] == "struct":
|
||||
extra_error = " Maybe you meant to use iterate_over."
|
||||
|
||||
fail("Attempted to access %r, but %r was not a struct - it had type %s.%s" % (full, parent, type["repr"], extra_error))
|
||||
|
||||
# buildifier: disable=unreachable
|
||||
return types.void
|
||||
|
||||
if part not in type["kv"] and full not in overrides:
|
||||
attrs = []
|
||||
for attr, value in sorted(type["kv"].items()):
|
||||
attrs.append("%s: %s" % (attr, value["repr"]))
|
||||
fail("Unable to find %r in %r, which had the following attributes:\n%s" % (part, parent, "\n".join(attrs)))
|
||||
|
||||
# buildifier: disable=unreachable
|
||||
return types.void
|
||||
|
||||
type = overrides.get(full, type["kv"][part])
|
||||
parent = full
|
||||
|
||||
return type
|
481
cc/toolchains/variables/BUILD
Normal file
481
cc/toolchains/variables/BUILD
Normal file
|
@ -0,0 +1,481 @@
|
|||
load("//cc/toolchains/impl:variables.bzl", "cc_builtin_variables", "cc_variable", "types")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_variable(
|
||||
name = "cs_fdo_instrument_path",
|
||||
actions = [
|
||||
"//cc/toolchains/actions:all_cc_link_actions",
|
||||
"//cc/toolchains/actions:all_compile_actions",
|
||||
],
|
||||
type = types.directory,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "def_file_path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "dependency_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "dependent_module_map_files",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.list(types.file)),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "external_include_paths",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.list(types.directory)),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "fdo_instrument_path",
|
||||
actions = [
|
||||
"//cc/toolchains/actions:all_cc_link_actions",
|
||||
"//cc/toolchains/actions:all_compile_actions",
|
||||
],
|
||||
type = types.directory,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "fdo_prefetch_hints_path",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "fdo_profile_path",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "force_pic",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# Provided when --force-pic is passed
|
||||
type = types.option(types.void),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "framework_include_paths",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "gcov_gcno_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "generate_interface_library",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# "yes" or "no"
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "include",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "include_paths",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "includes",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.list(types.file)),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "input_file",
|
||||
actions = ["//cc/toolchains/actions:strip"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "interface_library_builder_path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# Should be a file, but contains the string "ignored" when there's no value.
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "interface_library_input_path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# Should be a file, but contains the string "ignored" when there's no value.
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "interface_library_output_path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# Should be a file, but contains the string "ignored" when there's no value.
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "is_cc_test",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.bool),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "is_using_fission",
|
||||
actions = [
|
||||
"//cc/toolchains/actions:all_cc_link_actions",
|
||||
"//cc/toolchains/actions:all_compile_actions",
|
||||
],
|
||||
type = types.option(types.void),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "legacy_compile_flags",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "legacy_link_flags",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.list(types.struct(
|
||||
shared_libraries = types.list(types.struct(
|
||||
name = types.string,
|
||||
is_whole_archive = types.bool,
|
||||
object_files = types.list(types.file),
|
||||
path = types.file,
|
||||
type = types.string,
|
||||
)),
|
||||
))),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
# See :libraries_to_link.
|
||||
type = types.unknown,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries.is_whole_archive",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.string,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries.name",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.string,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries.object_files",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.list(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries.path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "libraries_to_link.shared_libraries.type",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.string,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "library_search_directories",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "linker_param_file",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "linkstamp_paths",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "lto_indexing_bitcode_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "module_files",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.list(types.file)),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "module_map_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "module_name",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "output_assembly_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "output_execpath",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "output_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "output_preprocess_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "per_object_debug_info_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "pic",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.void),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "preprocessor_defines",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "propellor_optimize_ld_path",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "quote_include_paths",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "runtime_library_search_directories",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.list(types.directory)),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "runtime_solib_name",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "serialized_diagnostics_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "source_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.file,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "strip_debug_symbols",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.void),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "stripopts",
|
||||
actions = ["//cc/toolchains/actions:strip"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "sysroot",
|
||||
type = types.directory,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "system_include_paths",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.directory),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_index",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_indexing_param_file",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_input_bitcode_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_merged_object_file",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_object_suffix_replace",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_output_object_file",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_param_file",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.file),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "thinlto_prefix_replace",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "unfiltered_compile_flags",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "user_compile_flags",
|
||||
actions = ["//cc/toolchains/actions:all_compile_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "user_link_flags",
|
||||
actions = ["//cc/toolchains/actions:all_cc_link_actions"],
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_builtin_variables(
|
||||
name = "variables",
|
||||
srcs = [
|
||||
":cs_fdo_instrument_path",
|
||||
":def_file_path",
|
||||
":dependency_file",
|
||||
":dependent_module_map_files",
|
||||
":external_include_paths",
|
||||
":fdo_instrument_path",
|
||||
":fdo_prefetch_hints_path",
|
||||
":fdo_profile_path",
|
||||
":force_pic",
|
||||
":framework_include_paths",
|
||||
":gcov_gcno_file",
|
||||
":generate_interface_library",
|
||||
":include",
|
||||
":include_paths",
|
||||
":includes",
|
||||
":input_file",
|
||||
":interface_library_builder_path",
|
||||
":interface_library_input_path",
|
||||
":interface_library_output_path",
|
||||
":is_cc_test",
|
||||
":is_using_fission",
|
||||
":legacy_compile_flags",
|
||||
":legacy_link_flags",
|
||||
":libraries_to_link",
|
||||
":library_search_directories",
|
||||
":linker_param_file",
|
||||
":linkstamp_paths",
|
||||
":lto_indexing_bitcode_file",
|
||||
":module_files",
|
||||
":module_map_file",
|
||||
":module_name",
|
||||
":output_assembly_file",
|
||||
":output_execpath",
|
||||
":output_file",
|
||||
":output_preprocess_file",
|
||||
":per_object_debug_info_file",
|
||||
":pic",
|
||||
":preprocessor_defines",
|
||||
":propellor_optimize_ld_path",
|
||||
":quote_include_paths",
|
||||
":runtime_library_search_directories",
|
||||
":runtime_solib_name",
|
||||
":serialized_diagnostics_file",
|
||||
":source_file",
|
||||
":strip_debug_symbols",
|
||||
":stripopts",
|
||||
":sysroot",
|
||||
":system_include_paths",
|
||||
":thinlto_index",
|
||||
":thinlto_indexing_param_file",
|
||||
":thinlto_input_bitcode_file",
|
||||
":thinlto_merged_object_file",
|
||||
":thinlto_object_suffix_replace",
|
||||
":thinlto_output_object_file",
|
||||
":thinlto_param_file",
|
||||
":thinlto_prefix_replace",
|
||||
":unfiltered_compile_flags",
|
||||
":user_compile_flags",
|
||||
":user_link_flags",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
52
tests/rule_based_toolchain/variables/BUILD
Normal file
52
tests/rule_based_toolchain/variables/BUILD
Normal file
|
@ -0,0 +1,52 @@
|
|||
load("//cc/toolchains/impl:variables.bzl", "cc_builtin_variables", "cc_variable", "types")
|
||||
load("//tests/rule_based_toolchain:analysis_test_suite.bzl", "analysis_test_suite")
|
||||
load(":variables_test.bzl", "TARGETS", "TESTS")
|
||||
|
||||
cc_variable(
|
||||
name = "str",
|
||||
type = types.string,
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "str_list",
|
||||
type = types.list(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "str_option",
|
||||
type = types.option(types.string),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "struct",
|
||||
actions = ["//tests/rule_based_toolchain/actions:c_compile"],
|
||||
type = types.struct(
|
||||
nested_str = types.string,
|
||||
nested_str_list = types.list(types.string),
|
||||
),
|
||||
)
|
||||
|
||||
cc_variable(
|
||||
name = "struct_list",
|
||||
type = types.list(types.struct(
|
||||
nested_str = types.string,
|
||||
nested_str_list = types.list(types.string),
|
||||
)),
|
||||
)
|
||||
|
||||
cc_builtin_variables(
|
||||
name = "variables",
|
||||
srcs = [
|
||||
":str",
|
||||
":str_list",
|
||||
":str_option",
|
||||
":struct",
|
||||
":struct_list",
|
||||
],
|
||||
)
|
||||
|
||||
analysis_test_suite(
|
||||
name = "test_suite",
|
||||
targets = TARGETS,
|
||||
tests = TESTS,
|
||||
)
|
128
tests/rule_based_toolchain/variables/variables_test.bzl
Normal file
128
tests/rule_based_toolchain/variables/variables_test.bzl
Normal file
|
@ -0,0 +1,128 @@
|
|||
# Copyright 2024 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.
|
||||
"""Tests for variables rule."""
|
||||
|
||||
load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeInfo", "BuiltinVariablesInfo", "VariableInfo")
|
||||
load("//cc/toolchains/impl:variables.bzl", "types", _get_type = "get_type")
|
||||
load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects")
|
||||
|
||||
visibility("private")
|
||||
|
||||
get_type = result_fn_wrapper(_get_type)
|
||||
|
||||
_ARGS_LABEL = Label("//:args")
|
||||
_NESTED_LABEL = Label("//:nested_vars")
|
||||
|
||||
def _type(target):
|
||||
return target[VariableInfo].type
|
||||
|
||||
def _types_represent_correctly_test(env, targets):
|
||||
env.expect.that_str(_type(targets.str_list)["repr"]).equals("List[string]")
|
||||
env.expect.that_str(_type(targets.str_option)["repr"]).equals("Option[string]")
|
||||
env.expect.that_str(_type(targets.struct)["repr"]).equals("struct(nested_str=string, nested_str_list=List[string])")
|
||||
env.expect.that_str(_type(targets.struct_list)["repr"]).equals("List[struct(nested_str=string, nested_str_list=List[string])]")
|
||||
|
||||
def _get_types_test(env, targets):
|
||||
c_compile = targets.c_compile[ActionTypeInfo]
|
||||
cpp_compile = targets.cpp_compile[ActionTypeInfo]
|
||||
variables = targets.variables[BuiltinVariablesInfo].variables
|
||||
|
||||
def expect_type(key, overrides = {}, expr = None, actions = []):
|
||||
return env.expect.that_value(
|
||||
get_type(
|
||||
variables = variables,
|
||||
overrides = overrides,
|
||||
args_label = _ARGS_LABEL,
|
||||
nested_label = _NESTED_LABEL,
|
||||
actions = actions,
|
||||
name = key,
|
||||
),
|
||||
# It's not a string, it's a complex recursive type, but string
|
||||
# supports .equals, which is all we care about.
|
||||
factory = subjects.result(subjects.str),
|
||||
expr = expr or key,
|
||||
)
|
||||
|
||||
expect_type("unknown").err().contains(
|
||||
"""The variable unknown does not exist. Did you mean one of the following?
|
||||
str
|
||||
str_list
|
||||
""",
|
||||
)
|
||||
|
||||
expect_type("str").ok().equals(types.string)
|
||||
expect_type("str.invalid").err().equals("""Attempted to access "str.invalid", but "str" was not a struct - it had type string.""")
|
||||
|
||||
expect_type("str_option").ok().equals(types.option(types.string))
|
||||
|
||||
expect_type("str_list").ok().equals(types.list(types.string))
|
||||
|
||||
expect_type("str_list.invalid").err().equals("""Attempted to access "str_list.invalid", but "str_list" was not a struct - it had type List[string].""")
|
||||
|
||||
expect_type("struct").ok().equals(_type(targets.struct))
|
||||
|
||||
expect_type("struct.nested_str_list").ok().equals(types.list(types.string))
|
||||
|
||||
expect_type("struct_list").ok().equals(_type(targets.struct_list))
|
||||
|
||||
expect_type("struct_list.nested_str_list").err().equals("""Attempted to access "struct_list.nested_str_list", but "struct_list" was not a struct - it had type List[struct(nested_str=string, nested_str_list=List[string])]. Maybe you meant to use iterate_over.""")
|
||||
|
||||
expect_type("struct.unknown").err().equals("""Unable to find "unknown" in "struct", which had the following attributes:
|
||||
nested_str: string
|
||||
nested_str_list: List[string]""")
|
||||
|
||||
expect_type("struct", actions = [c_compile]).ok()
|
||||
expect_type("struct", actions = [c_compile, cpp_compile]).err().equals(
|
||||
"The variable struct is inaccessible from the action %s. This is required because it is referenced in %s, which is included by %s, which references that action" % (cpp_compile.label, _NESTED_LABEL, _ARGS_LABEL),
|
||||
)
|
||||
|
||||
expect_type("struct.nested_str_list", actions = [c_compile]).ok()
|
||||
expect_type("struct.nested_str_list", actions = [c_compile, cpp_compile]).err()
|
||||
|
||||
# Simulate someone doing iterate_over = struct_list.
|
||||
expect_type(
|
||||
"struct_list",
|
||||
overrides = {"struct_list": _type(targets.struct)},
|
||||
expr = "struct_list_override",
|
||||
).ok().equals(_type(targets.struct))
|
||||
|
||||
expect_type(
|
||||
"struct_list.nested_str_list",
|
||||
overrides = {"struct_list": _type(targets.struct)},
|
||||
).ok().equals(types.list(types.string))
|
||||
|
||||
expect_type(
|
||||
"struct_list.nested_str_list",
|
||||
overrides = {
|
||||
"struct_list": _type(targets.struct),
|
||||
"struct_list.nested_str_list": types.string,
|
||||
},
|
||||
).ok().equals(types.string)
|
||||
|
||||
TARGETS = [
|
||||
"//tests/rule_based_toolchain/actions:c_compile",
|
||||
"//tests/rule_based_toolchain/actions:cpp_compile",
|
||||
":str",
|
||||
":str_list",
|
||||
":str_option",
|
||||
":struct",
|
||||
":struct_list",
|
||||
":variables",
|
||||
]
|
||||
|
||||
# @unsorted-dict-items
|
||||
TESTS = {
|
||||
"types_represent_correctly_test": _types_represent_correctly_test,
|
||||
"get_types_test": _get_types_test,
|
||||
}
|
Loading…
Reference in a new issue