mirror of https://github.com/bazelbuild/rules_cc
BEGIN_PUBLIC
Add support for testing rules_cc's new toolchains with rules_testing. END_PUBLIC PiperOrigin-RevId: 608769646 Change-Id: I1a698355e5e977cc86eedc7cf6e8e0f888593cb8
This commit is contained in:
parent
833f17060c
commit
2e780ceda9
|
@ -12,3 +12,4 @@ use_repo(cc_configure, "local_config_cc_toolchains")
|
||||||
register_toolchains("@local_config_cc_toolchains//:all")
|
register_toolchains("@local_config_cc_toolchains//:all")
|
||||||
|
|
||||||
bazel_dep(name = "bazel_skylib", version = "1.3.0", dev_dependency = True)
|
bazel_dep(name = "bazel_skylib", version = "1.3.0", dev_dependency = True)
|
||||||
|
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
|
||||||
|
|
|
@ -90,3 +90,10 @@ load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_
|
||||||
rules_proto_dependencies()
|
rules_proto_dependencies()
|
||||||
|
|
||||||
rules_proto_toolchains()
|
rules_proto_toolchains()
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "rules_testing",
|
||||||
|
sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4",
|
||||||
|
strip_prefix = "rules_testing-0.6.0",
|
||||||
|
url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.6.0/rules_testing-v0.6.0.tar.gz",
|
||||||
|
)
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
# that can access the providers directly.
|
# that can access the providers directly.
|
||||||
# Once it's stabilized, we *may* consider opening up parts of the API, or we may
|
# Once it's stabilized, we *may* consider opening up parts of the API, or we may
|
||||||
# decide to just require users to use the public user-facing rules.
|
# decide to just require users to use the public user-facing rules.
|
||||||
visibility("//third_party/bazel_rules/rules_cc/toolchains/...")
|
visibility([
|
||||||
|
"//cc/toolchains/...",
|
||||||
|
"//tests/...",
|
||||||
|
])
|
||||||
|
|
||||||
# Note that throughout this file, we never use a list. This is because mutable
|
# Note that throughout this file, we never use a list. This is because mutable
|
||||||
# types cannot be stored in depsets. Thus, we type them as a sequence in the
|
# types cannot be stored in depsets. Thus, we type them as a sequence in the
|
||||||
|
@ -120,12 +123,11 @@ ActionConfigInfo = provider(
|
||||||
# @unsorted-dict-items
|
# @unsorted-dict-items
|
||||||
fields = {
|
fields = {
|
||||||
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
|
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
|
||||||
"action_name": "(str) The name of the action",
|
"action": "(ActionTypeInfo) The name of the action",
|
||||||
"enabled": "(bool) If True, this action is enabled unless a rule type explicitly marks it as unsupported",
|
"enabled": "(bool) If True, this action is enabled unless a rule type explicitly marks it as unsupported",
|
||||||
"tools": "(Sequence[ToolInfo]) The tool applied to the action will be the first tool in the sequence with a feature set that matches the feature configuration",
|
"tools": "(Sequence[ToolInfo]) The tool applied to the action will be the first tool in the sequence with a feature set that matches the feature configuration",
|
||||||
"flag_sets": "(depset[FlagSetInfo]) Set of flag sets the action sets",
|
"flag_sets": "(Sequence[FlagSetInfo]) Set of flag sets the action sets",
|
||||||
"implies_features": "(depset[FeatureInfo]) Set of features implied by this action config",
|
"implies": "(depset[FeatureInfo]) Set of features implied by this action config",
|
||||||
"implies_action_configs": "(depset[ActionConfigInfo]) Set of action configs enabled by this action config",
|
|
||||||
"files": "(depset[File]) The files required to run these actions",
|
"files": "(depset[File]) The files required to run these actions",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
load("@rules_testing//lib:util.bzl", "util")
|
||||||
|
load("//cc/toolchains:actions.bzl", "cc_action_type", "cc_action_type_set")
|
||||||
|
load("//tests/rule_based_toolchain:analysis_test_suite.bzl", "analysis_test_suite")
|
||||||
|
load(":actions_test.bzl", "TARGETS", "TESTS")
|
||||||
|
|
||||||
|
util.helper_target(
|
||||||
|
cc_action_type,
|
||||||
|
name = "c_compile",
|
||||||
|
action_name = "c_compile",
|
||||||
|
visibility = ["//tests/rule_based_toolchain:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
|
util.helper_target(
|
||||||
|
cc_action_type,
|
||||||
|
name = "cpp_compile",
|
||||||
|
action_name = "cpp_compile",
|
||||||
|
visibility = ["//tests/rule_based_toolchain:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
|
util.helper_target(
|
||||||
|
cc_action_type_set,
|
||||||
|
name = "all_compile",
|
||||||
|
actions = [
|
||||||
|
":c_compile",
|
||||||
|
":cpp_compile",
|
||||||
|
],
|
||||||
|
visibility = ["//tests/rule_based_toolchain:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
|
analysis_test_suite(
|
||||||
|
name = "test_suite",
|
||||||
|
targets = TARGETS,
|
||||||
|
tests = TESTS,
|
||||||
|
)
|
|
@ -0,0 +1,43 @@
|
||||||
|
# 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 actions for the rule based toolchain."""
|
||||||
|
|
||||||
|
load(
|
||||||
|
"//cc/toolchains:cc_toolchain_info.bzl",
|
||||||
|
"ActionTypeInfo",
|
||||||
|
"ActionTypeSetInfo",
|
||||||
|
)
|
||||||
|
|
||||||
|
visibility("private")
|
||||||
|
|
||||||
|
def _test_action_types_impl(env, targets):
|
||||||
|
env.expect.that_target(targets.c_compile).provider(ActionTypeInfo) \
|
||||||
|
.name().equals("c_compile")
|
||||||
|
env.expect.that_target(targets.cpp_compile).provider(ActionTypeSetInfo) \
|
||||||
|
.actions().contains_exactly([targets.cpp_compile.label])
|
||||||
|
env.expect.that_target(targets.all_compile).provider(ActionTypeSetInfo) \
|
||||||
|
.actions().contains_exactly([
|
||||||
|
targets.c_compile.label,
|
||||||
|
targets.cpp_compile.label,
|
||||||
|
])
|
||||||
|
|
||||||
|
TARGETS = [
|
||||||
|
":c_compile",
|
||||||
|
":cpp_compile",
|
||||||
|
":all_compile",
|
||||||
|
]
|
||||||
|
|
||||||
|
TESTS = {
|
||||||
|
"actions_test": _test_action_types_impl,
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
# 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.
|
||||||
|
"""Test suites for the rule based toolchain."""
|
||||||
|
|
||||||
|
load("@rules_testing//lib:analysis_test.bzl", "analysis_test")
|
||||||
|
load(":subjects.bzl", "FACTORIES")
|
||||||
|
|
||||||
|
visibility("//tests/rule_based_toolchain/...")
|
||||||
|
|
||||||
|
_DEFAULT_TARGET = "//tests/rule_based_toolchain/actions:c_compile"
|
||||||
|
|
||||||
|
# Tests of internal starlark functions will often not require any targets,
|
||||||
|
# but analysis_test requires at least one, so we pick an arbitrary one.
|
||||||
|
def analysis_test_suite(name, tests, targets = [_DEFAULT_TARGET]):
|
||||||
|
"""A test suite for the internals of the toolchain.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: (str) The name of the test suite.
|
||||||
|
tests: (dict[str, fn]) A mapping from test name to implementations.
|
||||||
|
targets: (List[Label|str]) List of targets accessible to the test.
|
||||||
|
"""
|
||||||
|
targets = [native.package_relative_label(target) for target in targets]
|
||||||
|
|
||||||
|
test_case_names = []
|
||||||
|
for test_name, impl in tests.items():
|
||||||
|
if not test_name.endswith("_test"):
|
||||||
|
fail("Expected test keys to end with '_test', got test case %r" % test_name)
|
||||||
|
test_case_names.append(":" + test_name)
|
||||||
|
analysis_test(
|
||||||
|
name = test_name,
|
||||||
|
impl = impl,
|
||||||
|
provider_subject_factories = FACTORIES,
|
||||||
|
targets = {label.name: label for label in targets},
|
||||||
|
)
|
||||||
|
|
||||||
|
native.test_suite(
|
||||||
|
name = name,
|
||||||
|
tests = test_case_names,
|
||||||
|
)
|
|
@ -0,0 +1,127 @@
|
||||||
|
# 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.
|
||||||
|
"""Generates provider factories."""
|
||||||
|
|
||||||
|
load("@bazel_skylib//lib:structs.bzl", "structs")
|
||||||
|
load("@rules_testing//lib:truth.bzl", "subjects")
|
||||||
|
|
||||||
|
visibility("private")
|
||||||
|
|
||||||
|
def generate_factory(type, name, attrs):
|
||||||
|
"""Generates a factory for a custom struct.
|
||||||
|
|
||||||
|
There are three reasons we need to do so:
|
||||||
|
1. It's very difficult to read providers printed by these types.
|
||||||
|
eg. If you have a 10 layer deep diamond dependency graph, and try to
|
||||||
|
print the top value, the bottom value will be printed 2^10 times.
|
||||||
|
2. Collections of subjects are not well supported by rules_testing
|
||||||
|
eg. `FeatureInfo(flag_sets = [FlagSetInfo(...)])`
|
||||||
|
(You can do it, but the inner values are just regular bazel structs and
|
||||||
|
you can't do fluent assertions on them).
|
||||||
|
3. Recursive types are not supported at all
|
||||||
|
eg. `FeatureInfo(implies = depset([FeatureInfo(...)]))`
|
||||||
|
|
||||||
|
To solve this, we create a factory that:
|
||||||
|
* Validates that the types of the children are correct.
|
||||||
|
* Inlines providers to their labels when unambiguous.
|
||||||
|
|
||||||
|
For example, given:
|
||||||
|
|
||||||
|
```
|
||||||
|
foo = FeatureInfo(name = "foo", label = Label("//:foo"))
|
||||||
|
bar = FeatureInfo(..., implies = depset([foo]))
|
||||||
|
```
|
||||||
|
|
||||||
|
It would convert itself a subject for the following struct:
|
||||||
|
`FeatureInfo(..., implies = depset([Label("//:foo")]))`
|
||||||
|
|
||||||
|
Args:
|
||||||
|
type: (type) The type to create a factory for (eg. FooInfo)
|
||||||
|
name: (str) The name of the type (eg. "FooInfo")
|
||||||
|
attrs: (dict[str, Factory]) The attributes associated with this type.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A struct `FooFactory` suitable for use with
|
||||||
|
* `analysis_test(provider_subject_factories=[FooFactory])`
|
||||||
|
* `generate_factory(..., attrs=dict(foo = FooFactory))`
|
||||||
|
* `ProviderSequence(FooFactory)`
|
||||||
|
* `DepsetSequence(FooFactory)`
|
||||||
|
"""
|
||||||
|
attrs["label"] = subjects.label
|
||||||
|
|
||||||
|
want_keys = sorted(attrs.keys())
|
||||||
|
|
||||||
|
def validate(*, value, meta):
|
||||||
|
got_keys = sorted(structs.to_dict(value).keys())
|
||||||
|
if got_keys != want_keys:
|
||||||
|
meta.add_failure("Wanted a %s with keys %r, got %r" % (name, want_keys, got_keys), "")
|
||||||
|
|
||||||
|
def type_factory(value, *, meta):
|
||||||
|
validate(value = value, meta = meta)
|
||||||
|
|
||||||
|
transformed_value = {}
|
||||||
|
transformed_factories = {}
|
||||||
|
for field, factory in attrs.items():
|
||||||
|
field_value = getattr(value, field)
|
||||||
|
|
||||||
|
# If it's a type generated by generate_factory, inline it.
|
||||||
|
if hasattr(factory, "factory"):
|
||||||
|
factory.validate(value = field_value, meta = meta.derive(field))
|
||||||
|
transformed_value[field] = field_value.label
|
||||||
|
transformed_factories[field] = subjects.label
|
||||||
|
else:
|
||||||
|
transformed_value[field] = field_value
|
||||||
|
transformed_factories[field] = factory
|
||||||
|
|
||||||
|
return subjects.struct(
|
||||||
|
struct(**transformed_value),
|
||||||
|
meta = meta,
|
||||||
|
attrs = transformed_factories,
|
||||||
|
)
|
||||||
|
|
||||||
|
return struct(
|
||||||
|
type = type,
|
||||||
|
name = name,
|
||||||
|
factory = type_factory,
|
||||||
|
validate = validate,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _provider_collection(element_factory, fn):
|
||||||
|
def factory(value, *, meta):
|
||||||
|
value = fn(value)
|
||||||
|
|
||||||
|
# Validate that it really is the correct type
|
||||||
|
for i in range(len(value)):
|
||||||
|
element_factory.validate(
|
||||||
|
value = value[i],
|
||||||
|
meta = meta.derive("offset({})".format(i)),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Inline the providers to just labels.
|
||||||
|
return subjects.collection([v.label for v in value], meta = meta)
|
||||||
|
|
||||||
|
return factory
|
||||||
|
|
||||||
|
# This acts like a class, so we name it like one.
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
ProviderSequence = lambda element_factory: _provider_collection(
|
||||||
|
element_factory,
|
||||||
|
fn = lambda x: list(x),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
ProviderDepset = lambda element_factory: _provider_collection(
|
||||||
|
element_factory,
|
||||||
|
fn = lambda x: x.to_list(),
|
||||||
|
)
|
|
@ -0,0 +1,185 @@
|
||||||
|
# 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.
|
||||||
|
"""Test subjects for cc_toolchain_info providers."""
|
||||||
|
|
||||||
|
load("@rules_testing//lib:truth.bzl", "subjects")
|
||||||
|
load(
|
||||||
|
"//cc/toolchains:cc_toolchain_info.bzl",
|
||||||
|
"ActionConfigInfo",
|
||||||
|
"ActionConfigSetInfo",
|
||||||
|
"ActionTypeInfo",
|
||||||
|
"ActionTypeSetInfo",
|
||||||
|
"FeatureConstraintInfo",
|
||||||
|
"FeatureInfo",
|
||||||
|
"FeatureSetInfo",
|
||||||
|
"FlagGroupInfo",
|
||||||
|
"FlagSetInfo",
|
||||||
|
"MutuallyExclusiveCategoryInfo",
|
||||||
|
"ToolInfo",
|
||||||
|
)
|
||||||
|
load(":generate_factory.bzl", "ProviderDepset", "ProviderSequence", "generate_factory")
|
||||||
|
|
||||||
|
visibility("private")
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ActionTypeFactory = generate_factory(
|
||||||
|
ActionTypeInfo,
|
||||||
|
"ActionTypeInfo",
|
||||||
|
dict(
|
||||||
|
name = subjects.str,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ActionTypeSetFactory = generate_factory(
|
||||||
|
ActionTypeSetInfo,
|
||||||
|
"ActionTypeInfo",
|
||||||
|
dict(
|
||||||
|
actions = ProviderDepset(_ActionTypeFactory),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_MutuallyExclusiveCategoryFactory = generate_factory(
|
||||||
|
MutuallyExclusiveCategoryInfo,
|
||||||
|
"MutuallyExclusiveCategoryInfo",
|
||||||
|
dict(name = subjects.str),
|
||||||
|
)
|
||||||
|
|
||||||
|
_FEATURE_FLAGS = dict(
|
||||||
|
name = subjects.str,
|
||||||
|
enabled = subjects.bool,
|
||||||
|
flag_sets = None,
|
||||||
|
implies = None,
|
||||||
|
requires_any_of = None,
|
||||||
|
provides = ProviderSequence(_MutuallyExclusiveCategoryFactory),
|
||||||
|
known = subjects.bool,
|
||||||
|
overrides = None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Break the dependency loop.
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FakeFeatureFactory = generate_factory(
|
||||||
|
FeatureInfo,
|
||||||
|
"FeatureInfo",
|
||||||
|
_FEATURE_FLAGS,
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FeatureSetFactory = generate_factory(
|
||||||
|
FeatureSetInfo,
|
||||||
|
"FeatureSetInfo",
|
||||||
|
dict(features = _FakeFeatureFactory),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FeatureConstraintFactory = generate_factory(
|
||||||
|
FeatureConstraintInfo,
|
||||||
|
"FeatureConstraintInfo",
|
||||||
|
dict(
|
||||||
|
all_of = ProviderDepset(_FakeFeatureFactory),
|
||||||
|
none_of = ProviderDepset(_FakeFeatureFactory),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FlagGroupFactory = generate_factory(
|
||||||
|
FlagGroupInfo,
|
||||||
|
"FlagGroupInfo",
|
||||||
|
dict(
|
||||||
|
flags = subjects.collection,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FlagSetFactory = generate_factory(
|
||||||
|
FlagSetInfo,
|
||||||
|
"FlagSetInfo",
|
||||||
|
dict(
|
||||||
|
actions = ProviderDepset(_ActionTypeFactory),
|
||||||
|
# Use a collection here because we don't want to
|
||||||
|
flag_groups = subjects.collection,
|
||||||
|
requires_any_of = ProviderSequence(_FeatureConstraintFactory),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_FeatureFactory = generate_factory(
|
||||||
|
FeatureInfo,
|
||||||
|
"FeatureInfo",
|
||||||
|
_FEATURE_FLAGS | dict(
|
||||||
|
implies = ProviderDepset(_FakeFeatureFactory),
|
||||||
|
requires_any_of = ProviderSequence(_FeatureSetFactory),
|
||||||
|
overrides = _FakeFeatureFactory,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ToolFactory = generate_factory(
|
||||||
|
ToolInfo,
|
||||||
|
"ToolInfo",
|
||||||
|
dict(
|
||||||
|
exe = subjects.file,
|
||||||
|
runifles = subjects.depset_file,
|
||||||
|
requires_any_of = ProviderSequence(_FeatureConstraintFactory),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ActionConfigFactory = generate_factory(
|
||||||
|
ActionConfigInfo,
|
||||||
|
"ActionConfigInfo",
|
||||||
|
dict(
|
||||||
|
action = _ActionTypeFactory,
|
||||||
|
enabled = subjects.bool,
|
||||||
|
tools = ProviderSequence(_ToolFactory),
|
||||||
|
flag_sets = ProviderSequence(_FlagSetFactory),
|
||||||
|
implies = ProviderDepset(_FeatureFactory),
|
||||||
|
files = subjects.depset_file,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _action_config_set_factory_impl(value, *, meta):
|
||||||
|
# We can't use the usual strategy of "inline the labels" since all labels
|
||||||
|
# are the same.
|
||||||
|
transformed = {}
|
||||||
|
for ac in value.action_configs.to_list():
|
||||||
|
key = ac.action.label
|
||||||
|
if key in transformed:
|
||||||
|
meta.add_failure("Action declared twice in action config", key)
|
||||||
|
transformed[key] = _ActionConfigFactory.factory(
|
||||||
|
value = ac,
|
||||||
|
meta = meta.derive(".get({})".format(key)),
|
||||||
|
)
|
||||||
|
return transformed
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ActionConfigSetFactory = struct(
|
||||||
|
type = ActionConfigSetInfo,
|
||||||
|
name = "ActionConfigSetInfo",
|
||||||
|
factory = _action_config_set_factory_impl,
|
||||||
|
)
|
||||||
|
|
||||||
|
FACTORIES = [
|
||||||
|
_ActionTypeFactory,
|
||||||
|
_ActionTypeSetFactory,
|
||||||
|
_FlagGroupFactory,
|
||||||
|
_FlagSetFactory,
|
||||||
|
_MutuallyExclusiveCategoryFactory,
|
||||||
|
_FeatureFactory,
|
||||||
|
_FeatureConstraintFactory,
|
||||||
|
_FeatureSetFactory,
|
||||||
|
_ToolFactory,
|
||||||
|
_ActionConfigSetFactory,
|
||||||
|
]
|
Loading…
Reference in New Issue