Skip to content

Commit 9a00793

Browse files
allevatoluispadron
authored andcommitted
Implement swift_synthesize_interface_aspect.
This aspect uses the new `swift-synthesize-interface` driver mode that will be available in Swift 6.1 to generate a file that contains the synthesized Swift interface for a module (such as a C/Obj-C module), similar to the functionality provided by SourceKit. This can be used by IDEs and other clients to generate those interfaces without the complexity of a SourceKit invocation, which often do not play nicely with advanced build scenarios. PiperOrigin-RevId: 731345457
1 parent ec9283b commit 9a00793

21 files changed

+563
-7
lines changed

doc/api.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,31 @@ A struct containing the precompiled module and optional indexstore directory,
517517
or `None` if the toolchain or target does not support precompiled modules.
518518

519519

520+
<a id="swift_common.synthesize_interface"></a>
521+
522+
## swift_common.synthesize_interface
523+
524+
<pre>
525+
swift_common.synthesize_interface(<a href="#swift_common.synthesize_interface-actions">actions</a>, <a href="#swift_common.synthesize_interface-compilation_contexts">compilation_contexts</a>, <a href="#swift_common.synthesize_interface-feature_configuration">feature_configuration</a>, <a href="#swift_common.synthesize_interface-module_name">module_name</a>,
526+
<a href="#swift_common.synthesize_interface-output_file">output_file</a>, <a href="#swift_common.synthesize_interface-swift_infos">swift_infos</a>, <a href="#swift_common.synthesize_interface-swift_toolchain">swift_toolchain</a>)
527+
</pre>
528+
529+
Extracts the symbol graph from a Swift module.
530+
531+
**PARAMETERS**
532+
533+
534+
| Name | Description | Default Value |
535+
| :------------- | :------------- | :------------- |
536+
| <a id="swift_common.synthesize_interface-actions"></a>actions | The object used to register actions. | none |
537+
| <a id="swift_common.synthesize_interface-compilation_contexts"></a>compilation_contexts | A list of `CcCompilationContext`s that represent C/Objective-C requirements of the target being compiled, such as Swift-compatible preprocessor defines, header search paths, and so forth. These are typically retrieved from the `CcInfo` providers of a target's dependencies. | none |
538+
| <a id="swift_common.synthesize_interface-feature_configuration"></a>feature_configuration | The Swift feature configuration. | none |
539+
| <a id="swift_common.synthesize_interface-module_name"></a>module_name | The name of the module whose symbol graph should be extracted. | none |
540+
| <a id="swift_common.synthesize_interface-output_file"></a>output_file | A `File` into which the synthesized interface will be written. | none |
541+
| <a id="swift_common.synthesize_interface-swift_infos"></a>swift_infos | A list of `SwiftInfo` providers from dependencies of the target being compiled. This should include both propagated and non-propagated (implementation-only) dependencies. | none |
542+
| <a id="swift_common.synthesize_interface-swift_toolchain"></a>swift_toolchain | The `SwiftToolchainInfo` provider of the toolchain. | none |
543+
544+
520545
<a id="swift_common.use_toolchain"></a>
521546

522547
## swift_common.use_toolchain

swift/BUILD

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ bzl_library(
9696
deps = [
9797
"//swift/internal:compiling",
9898
"//swift/internal:features",
99+
"//swift/internal:interface_synthesizing",
99100
"//swift/internal:linking",
100101
"//swift/internal:symbol_graph_extracting",
101102
"//swift/internal:toolchain_utils",
@@ -207,7 +208,6 @@ bzl_library(
207208
"//swift/internal:utils",
208209
"@bazel_skylib//lib:dicts",
209210
"@bazel_skylib//lib:sets",
210-
"@bazel_skylib//rules:common_settings",
211211
],
212212
)
213213

@@ -249,6 +249,7 @@ bzl_library(
249249
"//swift/internal:attrs",
250250
"//swift/internal:feature_names",
251251
"//swift/internal:providers",
252+
"//swift/internal:toolchain_utils",
252253
"//swift/internal:utils",
253254
],
254255
)
@@ -280,6 +281,18 @@ bzl_library(
280281
],
281282
)
282283

284+
bzl_library(
285+
name = "swift_synthesize_interface_aspect",
286+
srcs = ["swift_synthesize_interface_aspect.bzl"],
287+
deps = [
288+
":providers",
289+
":swift_clang_module_aspect",
290+
"//swift/internal:features",
291+
"//swift/internal:interface_synthesizing",
292+
"//swift/internal:toolchain_utils",
293+
],
294+
)
295+
283296
bzl_library(
284297
name = "swift_test",
285298
srcs = ["swift_test.bzl"],
@@ -290,6 +303,7 @@ bzl_library(
290303
"//swift/internal:compiling",
291304
"//swift/internal:env_expansion",
292305
"//swift/internal:feature_names",
306+
"//swift/internal:interface_synthesizing",
293307
"//swift/internal:linking",
294308
"//swift/internal:output_groups",
295309
"//swift/internal:providers",
@@ -326,6 +340,7 @@ bzl_library(
326340
":swift_overlay_helpers",
327341
":swift_package_configuration",
328342
":swift_symbol_graph_aspect",
343+
":swift_synthesize_interface_aspect",
329344
":swift_test",
330345
],
331346
)

swift/internal/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ bzl_library(
162162
],
163163
)
164164

165+
bzl_library(
166+
name = "interface_synthesizing",
167+
srcs = ["interface_synthesizing.bzl"],
168+
visibility = ["//swift:__subpackages__"],
169+
deps = [
170+
":action_names",
171+
":actions",
172+
":utils",
173+
"//swift:providers",
174+
],
175+
)
176+
165177
bzl_library(
166178
name = "linking",
167179
srcs = ["linking.bzl"],

swift/internal/action_names.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ SWIFT_ACTION_PRECOMPILE_C_MODULE = "SwiftPrecompileCModule"
4646
# other tooling.
4747
SWIFT_ACTION_SYMBOL_GRAPH_EXTRACT = "SwiftSymbolGraphExtract"
4848

49+
# Synthesizes the Swift interface from a compiled module.
50+
SWIFT_ACTION_SYNTHESIZE_INTERFACE = "SwiftSynthesizeInterface"
51+
4952
def all_action_names():
5053
"""A convenience function to return all actions defined by this rule set."""
5154
return (
@@ -57,4 +60,5 @@ def all_action_names():
5760
SWIFT_ACTION_MODULEWRAP,
5861
SWIFT_ACTION_PRECOMPILE_C_MODULE,
5962
SWIFT_ACTION_SYMBOL_GRAPH_EXTRACT,
63+
SWIFT_ACTION_SYNTHESIZE_INTERFACE,
6064
)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright 2025 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Functions relating to synthesizing Swift interfaces from non-Swift targets."""
16+
17+
load("//swift:providers.bzl", "SwiftInfo")
18+
load(":action_names.bzl", "SWIFT_ACTION_SYNTHESIZE_INTERFACE")
19+
load(":actions.bzl", "run_toolchain_action")
20+
load(":utils.bzl", "merge_compilation_contexts")
21+
22+
def synthesize_interface(
23+
*,
24+
actions,
25+
compilation_contexts,
26+
feature_configuration,
27+
module_name,
28+
output_file,
29+
swift_infos,
30+
swift_toolchain):
31+
"""Extracts the symbol graph from a Swift module.
32+
33+
Args:
34+
actions: The object used to register actions.
35+
compilation_contexts: A list of `CcCompilationContext`s that represent
36+
C/Objective-C requirements of the target being compiled, such as
37+
Swift-compatible preprocessor defines, header search paths, and so
38+
forth. These are typically retrieved from the `CcInfo` providers of
39+
a target's dependencies.
40+
feature_configuration: The Swift feature configuration.
41+
module_name: The name of the module whose symbol graph should be
42+
extracted.
43+
output_file: A `File` into which the synthesized interface will be
44+
written.
45+
swift_infos: A list of `SwiftInfo` providers from dependencies of the
46+
target being compiled. This should include both propagated and
47+
non-propagated (implementation-only) dependencies.
48+
swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain.
49+
"""
50+
merged_compilation_context = merge_compilation_contexts(
51+
transitive_compilation_contexts = compilation_contexts + [
52+
cc_info.compilation_context
53+
for cc_info in swift_toolchain.implicit_deps_providers.cc_infos
54+
],
55+
)
56+
merged_swift_info = SwiftInfo(
57+
swift_infos = (
58+
swift_infos + swift_toolchain.implicit_deps_providers.swift_infos
59+
),
60+
)
61+
62+
# Flattening this `depset` is necessary because we need to extract the
63+
# module maps or precompiled modules out of structured values and do so
64+
# conditionally.
65+
transitive_modules = merged_swift_info.transitive_modules.to_list()
66+
67+
transitive_swiftmodules = []
68+
for module in transitive_modules:
69+
swift_module = module.swift
70+
if swift_module:
71+
transitive_swiftmodules.append(swift_module.swiftmodule)
72+
73+
prerequisites = struct(
74+
bin_dir = feature_configuration._bin_dir,
75+
cc_compilation_context = merged_compilation_context,
76+
genfiles_dir = feature_configuration._genfiles_dir,
77+
is_swift = True,
78+
module_name = module_name,
79+
output_file = output_file,
80+
target_label = feature_configuration._label,
81+
transitive_modules = transitive_modules,
82+
transitive_swiftmodules = transitive_swiftmodules,
83+
)
84+
85+
run_toolchain_action(
86+
actions = actions,
87+
action_name = SWIFT_ACTION_SYNTHESIZE_INTERFACE,
88+
feature_configuration = feature_configuration,
89+
outputs = [output_file],
90+
prerequisites = prerequisites,
91+
progress_message = (
92+
"Synthesizing Swift interface for {}".format(module_name)
93+
),
94+
swift_toolchain = swift_toolchain,
95+
)

swift/providers.bzl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,31 @@ has the same fields as documented in `direct_symbol_graphs`.
269269
},
270270
)
271271

272+
SwiftSynthesizedInterfaceInfo = provider(
273+
doc = "Propagates synthesized Swift interfaces for modules.",
274+
fields = {
275+
"direct_modules": """\
276+
`List` of `struct`s representing the synthesized interfaces for the modules in
277+
the target that propagated this provider. This list will be empty if propagated
278+
by a target that does not contain any modules that Swift can synthesize an
279+
interface for (i.e., C, or Swift itself), but its `transitive_modules` may be
280+
non-empty if it has dependencies for which interfaces can be synthesized.
281+
282+
Each `struct` has the following fields:
283+
284+
* `module_name`: A string denoting the name of the module whose interface is
285+
synthesized.
286+
287+
* `synthesized_interface`: A `File` containing the synthesized interface.
288+
""",
289+
"transitive_modules": """\
290+
`Depset` of `struct`s representing the synthesized interfaces for the modules in
291+
the target that propagated this provider and all of its dependencies. Each
292+
`struct` has the same fields as documented in `direct_modules`.
293+
""",
294+
},
295+
)
296+
272297
SwiftToolchainInfo = provider(
273298
doc = """
274299
Propagates information about a Swift toolchain to compilation and linking rules

swift/swift.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ load(
3333
_SwiftProtoCompilerInfo = "SwiftProtoCompilerInfo",
3434
_SwiftProtoInfo = "SwiftProtoInfo",
3535
_SwiftSymbolGraphInfo = "SwiftSymbolGraphInfo",
36+
_SwiftSynthesizedInterfaceInfo = "SwiftSynthesizedInterfaceInfo",
3637
_SwiftToolchainInfo = "SwiftToolchainInfo",
3738
)
3839
load(":swift_binary.bzl", _swift_binary = "swift_binary")
@@ -61,13 +62,18 @@ load(
6162
":swift_symbol_graph_aspect.bzl",
6263
_swift_symbol_graph_aspect = "swift_symbol_graph_aspect",
6364
)
65+
load(
66+
":swift_synthesize_interface_aspect.bzl",
67+
_swift_synthesize_interface_aspect = "swift_synthesize_interface_aspect",
68+
)
6469
load(":swift_test.bzl", _swift_test = "swift_test")
6570

6671
# Re-export providers.
6772
SwiftInfo = _SwiftInfo
6873
SwiftProtoCompilerInfo = _SwiftProtoCompilerInfo
6974
SwiftProtoInfo = _SwiftProtoInfo
7075
SwiftSymbolGraphInfo = _SwiftSymbolGraphInfo
76+
SwiftSynthesizedInterfaceInfo = _SwiftSynthesizedInterfaceInfo
7177
SwiftToolchainInfo = _SwiftToolchainInfo
7278

7379
# Re-export public API module.
@@ -89,3 +95,4 @@ swift_test = _swift_test
8995
# Re-export public aspects.
9096
swift_clang_module_aspect = _swift_clang_module_aspect
9197
swift_symbol_graph_aspect = _swift_symbol_graph_aspect
98+
swift_synthesize_interface_aspect = _swift_synthesize_interface_aspect

swift/swift_common.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ load(
3333
"get_cc_feature_configuration",
3434
"is_feature_enabled",
3535
)
36+
load(
37+
"//swift/internal:interface_synthesizing.bzl",
38+
"synthesize_interface",
39+
)
3640
load(
3741
"//swift/internal:linking.bzl",
3842
"create_linking_context_from_compilation_outputs",
@@ -60,5 +64,6 @@ swift_common = struct(
6064
get_toolchain = get_swift_toolchain,
6165
is_enabled = is_feature_enabled,
6266
precompile_clang_module = precompile_clang_module,
67+
synthesize_interface = synthesize_interface,
6368
use_toolchain = use_swift_toolchain,
6469
)

0 commit comments

Comments
 (0)