diff --git a/doc/rules.md b/doc/rules.md index 4e85ccadd..baab8cb0d 100644 --- a/doc/rules.md +++ b/doc/rules.md @@ -212,7 +212,7 @@ the future, this rule is not recommended for other widespread use. ## swift_feature_allowlist
-swift_feature_allowlist(name, managed_features, packages)
+swift_feature_allowlist(name, aspect_ids, managed_features, packages)
 
Limits the ability to request or disable certain features to a set of packages @@ -233,7 +233,8 @@ package. | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | -| managed_features | A list of feature strings that are permitted to be specified by the targets in the packages matched by the `packages` attribute. This list may include both feature names and/or negations (a name with a leading `-`); a regular feature name means that the targets in the matching packages may explicitly request that the feature be enabled, and a negated feature means that the target may explicitly request that the feature be disabled.

For example, `managed_features = ["foo", "-bar"]` means that targets in the allowlist's packages may request that feature `"foo"` be enabled and that feature `"bar"` be disabled. | List of strings | optional | `[]` | +| aspect_ids | A list of strings representing the identifiers of aspects that are allowed to enable/disable the features in `managed_features`, even when the aspect is applied to packages not covered by the `packages` attribute.

Aspect identifiers are each expected to be of the form `<.bzl file label>%` (i.e., the form one would use if invoking it from the command line, as described at https://bazel.build/extending/aspects#invoking_the_aspect_using_the_command_line). | List of strings | optional | `[]` | +| managed_features | A list of feature strings that are permitted to be specified by the targets in the packages matched by the `packages` attribute *or* an aspect whose name matches the `aspect_ids` attribute (in any package). This list may include both feature names and/or negations (a name with a leading `-`); a regular feature name means that the matching targets/aspects may explicitly request that the feature be enabled, and a negated feature means that the target may explicitly request that the feature be disabled.

For example, `managed_features = ["foo", "-bar"]` means that targets in the allowlist's packages/aspects may request that feature `"foo"` be enabled and that feature `"bar"` be disabled. | List of strings | optional | `[]` | | packages | A list of strings representing packages (possibly recursive) whose targets are allowed to enable/disable the features in `managed_features`. Each package pattern is written in the syntax used by the `package_group` function:

* `//foo/bar`: Targets in the package `//foo/bar` but not in subpackages.

* `//foo/bar/...`: Targets in the package `//foo/bar` and any of its subpackages.

* A leading `-` excludes packages that would otherwise have been included by the patterns in the list.

Exclusions always take priority over inclusions; order in the list is irrelevant. | List of strings | required | | diff --git a/swift/internal/features.bzl b/swift/internal/features.bzl index 441e693e9..758dc4f4d 100644 --- a/swift/internal/features.bzl +++ b/swift/internal/features.bzl @@ -87,9 +87,25 @@ def configure_features( "parse_headers", ]) + # HACK: This is the only way today to check whether the caller is inside an + # aspect. We have to do this because accessing `ctx.aspect_ids` halts the + # build if called from outside an aspect, but we can't use `hasattr` to + # check if it's safe because the attribute is always present on both rule + # and aspect contexts. + # TODO: b/319132714 - Replace this with a real API. + is_aspect = repr(ctx).startswith("%` (i.e., the form one would use if +invoking it from the command line, as described at +https://bazel.build/extending/aspects#invoking_the_aspect_using_the_command_line). +""", + ), "managed_features": attr.string_list( allow_empty = True, doc = """\ A list of feature strings that are permitted to be specified by the targets in -the packages matched by the `packages` attribute. This list may include both +the packages matched by the `packages` attribute *or* an aspect whose name +matches the `aspect_ids` attribute (in any package). This list may include both feature names and/or negations (a name with a leading `-`); a regular feature -name means that the targets in the matching packages may explicitly request that -the feature be enabled, and a negated feature means that the target may -explicitly request that the feature be disabled. +name means that the matching targets/aspects may explicitly request that the +feature be enabled, and a negated feature means that the target may explicitly +request that the feature be disabled. For example, `managed_features = ["foo", "-bar"]` means that targets in the -allowlist's packages may request that feature `"foo"` be enabled and that -feature `"bar"` be disabled. +allowlist's packages/aspects may request that feature `"foo"` be enabled and +that feature `"bar"` be disabled. """, mandatory = False, ),