Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit 24a0449

Browse files
allevatoswiple-rules-gardener
authored andcommitted
API changes to create_swift_interop_info.
- Require all dependencies' `SwiftInfo`s to be passed instead of implicitly (and unconditionally) traversing `deps`. - Add `requested_features` and `unsupported_features` parameters so rule implementations can provide these values (to be automatically added to the values on the target) as if they were supplying the feature configuration themselves. - Correctly derive a module name if it is not provided. PiperOrigin-RevId: 368653094
1 parent ec94196 commit 24a0449

File tree

1 file changed

+101
-54
lines changed

1 file changed

+101
-54
lines changed

swift/internal/swift_clang_module_aspect.bzl

Lines changed: 101 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,10 @@ _SINGLE_TARGET_ASPECT_ATTRS = [
4949

5050
_SwiftInteropInfo = provider(
5151
doc = """\
52-
Contains minimal information required for the `swift_clang_module_aspect` to
53-
generate a module map and/or precompiled module for a target so that it can
54-
expose C/Objective-C APIs to Swift.
52+
Contains minimal information required to allow `swift_clang_module_aspect` to
53+
manage the creation of a `SwiftInfo` provider for a C/Objective-C target.
5554
""",
5655
fields = {
57-
"additional_swift_infos": """\
58-
A list of additional `SwiftInfo` providers from dependencies that aren't
59-
reachable via the `deps` attribute of the rule propagating this provider, but
60-
which should be treated as dependencies of the C/Objective-C module.
61-
""",
6256
"module_map": """\
6357
A `File` representing an existing module map that should be used to represent
6458
the module, or `None` if the module map should be generated based on the headers
@@ -67,15 +61,39 @@ in the target's compilation context.
6761
"module_name": """\
6862
A string denoting the name of the module, or `None` if the name should be
6963
derived automatically from the target label.
64+
""",
65+
"requested_features": """\
66+
A list of features that should be enabled for the target, in addition to those
67+
supplied in the `features` attribute, unless the feature is otherwise marked as
68+
unsupported (either on the target or by the toolchain). This allows the rule
69+
implementation to supply an additional set of fixed features that should always
70+
be enabled when the aspect processes that target; for example, a rule can
71+
request that `swift.emit_c_module` always be enabled for its targets even if it
72+
is not explicitly enabled in the toolchain or on the target directly.
73+
""",
74+
"swift_infos": """\
75+
A list of `SwiftInfo` providers from dependencies of the target, which will be
76+
merged with the new `SwiftInfo` created by the aspect.
77+
""",
78+
"unsupported_features": """\
79+
A list of features that should be disabled for the target, in addition to those
80+
supplied as negations in the `features` attribute. This allows the rule
81+
implementation to supply an additional set of fixed features that should always
82+
be disabled when the aspect processes that target; for example, a rule that
83+
processes frameworks with headers that do not follow strict layering can request
84+
that `swift.strict_module` always be disabled for its targets even if it is
85+
enabled by default in the toolchain.
7086
""",
7187
},
7288
)
7389

7490
def create_swift_interop_info(
7591
*,
76-
additional_swift_infos = [],
7792
module_map = None,
78-
module_name = None):
93+
module_name = None,
94+
requested_features = [],
95+
swift_infos = [],
96+
unsupported_features = []):
7997
"""Returns a provider that lets a target expose C/Objective-C APIs to Swift.
8098
8199
The provider returned by this function allows custom build rules written in
@@ -85,34 +103,54 @@ def create_swift_interop_info(
85103
make into a module, and then also propagate the provider returned from this
86104
function.
87105
88-
The simplest usage is for the custom rule to simply return
89-
`swift_common.create_swift_interop_info()` without any arguments; this
90-
tells `swift_clang_module_aspect` to derive the module name from the target
91-
label and create a module map using the headers from the compilation
92-
context.
106+
The simplest usage is for a custom rule to call
107+
`swift_common.create_swift_interop_info` passing it only the list of
108+
`SwiftInfo` providers from its dependencies; this tells
109+
`swift_clang_module_aspect` to derive the module name from the target label
110+
and create a module map using the headers from the compilation context.
93111
94112
If the custom rule has reason to provide its own module name or module map,
95113
then it can do so using the `module_name` and `module_map` arguments.
96114
97-
The `swift_clang_module_aspect` automatically traverses the `deps` attribute
98-
of even custom rules, so those rules don't need to do anything extra to
99-
collect those dependencies. However, if a custom rule has dependencies in
100-
other attributes (such as a runtime library specified as the default value
101-
of a private attribute), it should pass the `SwiftInfo` provider from that
102-
target into this function via the `additional_swift_infos` argument.
115+
When a rule returns this provider, it must provide the full set of
116+
`SwiftInfo` providers from dependencies that will be merged with the one
117+
that `swift_clang_module_aspect` creates for the target itself; the aspect
118+
will not do so automatically. This allows the rule to not only add extra
119+
dependencies (such as support libraries from implicit attributes) but also
120+
exclude dependencies if necessary.
103121
104122
Args:
105-
additional_swift_infos: A list of additional `SwiftInfo` providers from
106-
dependencies that aren't reachable via the `deps` attribute of the
107-
rule propagating this provider, but which should be treated as
108-
dependencies of the C/Objective-C module.
109123
module_map: A `File` representing an existing module map that should be
110-
used to represent the module, or `None` if the module map should be
111-
generated based on the headers in the target's compilation context.
112-
If this argument is provided, then `module_name` must also be
113-
provided.
114-
module_name: A string denoting the name of the module, or `None` if the
115-
name should be derived automatically from the target label.
124+
used to represent the module, or `None` (the default) if the module
125+
map should be generated based on the headers in the target's
126+
compilation context. If this argument is provided, then
127+
`module_name` must also be provided.
128+
module_name: A string denoting the name of the module, or `None` (the
129+
default) if the name should be derived automatically from the target
130+
label.
131+
requested_features: A list of features (empty by default) that should be
132+
requested for the target, which are added to those supplied in the
133+
`features` attribute of the target. These features will be enabled
134+
unless they are otherwise marked as unsupported (either on the
135+
target or by the toolchain). This allows the rule implementation to
136+
have additional control over features that should be supported by
137+
default for all instances of that rule as if it were creating the
138+
feature configuration itself; for example, a rule can request that
139+
`swift.emit_c_module` always be enabled for its targets even if it
140+
is not explicitly enabled in the toolchain or on the target
141+
directly.
142+
swift_infos: A list of `SwiftInfo` providers from dependencies, which
143+
will be merged with the new `SwiftInfo` created by the aspect.
144+
unsupported_features: A list of features (empty by default) that should
145+
be considered unsupported for the target, which are added to those
146+
supplied as negations in the `features` attribute. This allows the
147+
rule implementation to have additional control over features that
148+
should be disabled by default for all instances of that rule as if
149+
it were creating the feature configuration itself; for example, a
150+
rule that processes frameworks with headers that do not follow
151+
strict layering can request that `swift.strict_module` always be
152+
disabled for its targets even if it is enabled by default in the
153+
toolchain.
116154
117155
Returns:
118156
A provider whose type/layout is an implementation detail and should not
@@ -122,9 +160,11 @@ def create_swift_interop_info(
122160
fail("'module_name' must be specified when 'module_map' is specified.")
123161

124162
return _SwiftInteropInfo(
125-
additional_swift_infos = additional_swift_infos,
126163
module_map = module_map,
127164
module_name = module_name,
165+
requested_features = requested_features,
166+
swift_infos = swift_infos,
167+
unsupported_features = unsupported_features,
128168
)
129169

130170
def _tagged_target_module_name(label, tags):
@@ -485,40 +525,47 @@ def _swift_clang_module_aspect_impl(target, aspect_ctx):
485525
if SwiftInfo in target:
486526
return []
487527

488-
# Collect `SwiftInfo` providers from dependencies, based on the attributes
489-
# that this aspect traverses.
490-
attr = aspect_ctx.rule.attr
491-
deps = []
492-
for attr_name in _MULTIPLE_TARGET_ASPECT_ATTRS:
493-
deps.extend(getattr(attr, attr_name, []))
494-
for attr_name in _SINGLE_TARGET_ASPECT_ATTRS:
495-
dep = getattr(attr, attr_name, None)
496-
if dep:
497-
deps.append(dep)
498-
swift_infos = get_providers(deps, SwiftInfo)
499-
500-
swift_toolchain = aspect_ctx.attr._toolchain_for_aspect[SwiftToolchainInfo]
501-
feature_configuration = configure_features(
502-
ctx = aspect_ctx,
503-
requested_features = aspect_ctx.features,
504-
swift_toolchain = swift_toolchain,
505-
unsupported_features = aspect_ctx.disabled_features,
506-
)
507-
508528
if CcInfo in target:
509529
compilation_context = target[CcInfo].compilation_context
510530
else:
511531
compilation_context = None
512532

533+
requested_features = aspect_ctx.features
534+
unsupported_features = aspect_ctx.disabled_features
535+
513536
if _SwiftInteropInfo in target:
514537
interop_info = target[_SwiftInteropInfo]
515-
swift_infos.extend(interop_info.additional_swift_infos)
516538
module_map_file = interop_info.module_map
517-
module_name = interop_info.module_name
539+
module_name = (
540+
interop_info.module_name or derive_module_name(target.label)
541+
)
542+
swift_infos = interop_info.swift_infos
543+
requested_features.extend(interop_info.requested_features)
544+
unsupported_features.extend(interop_info.unsupported_features)
518545
else:
519546
module_map_file = None
520547
module_name = None
521548

549+
# Collect `SwiftInfo` providers from dependencies, based on the
550+
# attributes that this aspect traverses.
551+
deps = []
552+
attr = aspect_ctx.rule.attr
553+
for attr_name in _MULTIPLE_TARGET_ASPECT_ATTRS:
554+
deps.extend(getattr(attr, attr_name, []))
555+
for attr_name in _SINGLE_TARGET_ASPECT_ATTRS:
556+
dep = getattr(attr, attr_name, None)
557+
if dep:
558+
deps.append(dep)
559+
swift_infos = get_providers(deps, SwiftInfo)
560+
561+
swift_toolchain = aspect_ctx.attr._toolchain_for_aspect[SwiftToolchainInfo]
562+
feature_configuration = configure_features(
563+
ctx = aspect_ctx,
564+
requested_features = requested_features,
565+
swift_toolchain = swift_toolchain,
566+
unsupported_features = unsupported_features,
567+
)
568+
522569
if (
523570
_SwiftInteropInfo in target or
524571
apple_common.Objc in target or

0 commit comments

Comments
 (0)