Skip to content

Commit 477df3a

Browse files
authored
Add support for emitting private swiftinterface (#1176)
This PR adds a new feature: `swift.emit_private_swiftinterface` which enables emitting `.private.swiftinterface` files for Swift modules. These interface files are required when using `@_spi` and library evolution. ## Example ``` bazel build //examples/apple/private_swiftinterface ``` ``` Target //examples/apple/private_swiftinterface:private_swiftinterface up-to-date: bazel-bin/examples/apple/private_swiftinterface/PrivateSwiftInterfaceLib.swiftdoc bazel-bin/examples/apple/private_swiftinterface/PrivateSwiftInterfaceLib.swiftinterface bazel-bin/examples/apple/private_swiftinterface/PrivateSwiftInterfaceLib.private.swiftinterface bazel-bin/examples/apple/private_swiftinterface/PrivateSwiftInterfaceLib.swiftmodule bazel-bin/examples/apple/private_swiftinterface/PrivateSwiftInterfaceLib.swiftsourceinfo bazel-bin/examples/apple/private_swiftinterface/libprivate_swiftinterface.a ```
1 parent d4e6589 commit 477df3a

17 files changed

+282
-12
lines changed

doc/api.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ A provider whose type/layout is an implementation detail and should not
474474

475475
<pre>
476476
swift_common.create_swift_module(<a href="#swift_common.create_swift_module-swiftdoc">swiftdoc</a>, <a href="#swift_common.create_swift_module-swiftmodule">swiftmodule</a>, <a href="#swift_common.create_swift_module-ast_files">ast_files</a>, <a href="#swift_common.create_swift_module-defines">defines</a>, <a href="#swift_common.create_swift_module-indexstore">indexstore</a>, <a href="#swift_common.create_swift_module-plugins">plugins</a>,
477-
<a href="#swift_common.create_swift_module-swiftsourceinfo">swiftsourceinfo</a>, <a href="#swift_common.create_swift_module-swiftinterface">swiftinterface</a>, <a href="#swift_common.create_swift_module-symbol_graph">symbol_graph</a>)
477+
<a href="#swift_common.create_swift_module-swiftsourceinfo">swiftsourceinfo</a>, <a href="#swift_common.create_swift_module-swiftinterface">swiftinterface</a>, <a href="#swift_common.create_swift_module-private_swiftinterface">private_swiftinterface</a>,
478+
<a href="#swift_common.create_swift_module-symbol_graph">symbol_graph</a>)
478479
</pre>
479480

480481
Creates a value representing a Swift module use as a Swift dependency.
@@ -492,6 +493,7 @@ Creates a value representing a Swift module use as a Swift dependency.
492493
| <a id="swift_common.create_swift_module-plugins"></a>plugins | A list of `SwiftCompilerPluginInfo` providers representing compiler plugins that are required by this module and should be loaded by the compiler when this module is directly depended on. | `[]` |
493494
| <a id="swift_common.create_swift_module-swiftsourceinfo"></a>swiftsourceinfo | The `.swiftsourceinfo` file emitted by the compiler for this module. May be `None` if no source info file was emitted. | `None` |
494495
| <a id="swift_common.create_swift_module-swiftinterface"></a>swiftinterface | The `.swiftinterface` file emitted by the compiler for this module. May be `None` if no module interface file was emitted. | `None` |
496+
| <a id="swift_common.create_swift_module-private_swiftinterface"></a>private_swiftinterface | The `.private.swiftinterface` file emitted by the compiler for this module. May be `None` if no private module interface file was emitted. | `None` |
495497
| <a id="swift_common.create_swift_module-symbol_graph"></a>symbol_graph | A `File` representing the directory that contains the symbol graph data generated by the compiler if the `"swift.emit_symbol_graph"` feature is enabled, otherwise this will be `None`. | `None` |
496498

497499
**RETURNS**

proto/swift_proto_library.bzl

+3-2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def _swift_proto_library_impl(ctx):
185185
files = depset(compact([
186186
module_context.swift.swiftdoc,
187187
module_context.swift.swiftinterface,
188+
module_context.swift.private_swiftinterface,
188189
module_context.swift.swiftmodule,
189190
module_context.swift.swiftsourceinfo,
190191
linking_output.library_to_link.static_library,
@@ -266,7 +267,7 @@ from which the Swift protos will be generated.
266267
],
267268
default = [],
268269
doc = """\
269-
List of additional dependencies required by the generated Swift code at compile time,
270+
List of additional dependencies required by the generated Swift code at compile time,
270271
whose SwiftProtoInfo will be ignored.
271272
""",
272273
),
@@ -298,7 +299,7 @@ swift_proto_library(
298299
)
299300
```
300301
301-
If your protos depend on protos from other targets, add dependencies between the
302+
If your protos depend on protos from other targets, add dependencies between the
302303
swift_proto_library targets which mirror the dependencies between the proto targets.
303304
304305
```python

swift/BUILD

+6
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ bool_setting(
109109
build_setting_default = False,
110110
)
111111

112+
# Configuration setting for enabling the generation of private swiftinterface files (e.g. those for `@_spi`).
113+
bool_setting(
114+
name = "emit_private_swiftinterface",
115+
build_setting_default = False,
116+
)
117+
112118
# NOTE: Enabling this flag will transition --proto_compiler to
113119
# //tools/protoc_wrapper:protoc for swift_grpc_library and swift_proto_library,
114120
# unless you set --proto_compiler manually.

swift/deprecated_proto/swift_protoc_gen_aspect.bzl

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ load(
4040
)
4141
load(
4242
"//swift/internal:feature_names.bzl",
43+
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
4344
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
4445
"SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION",
4546
"SWIFT_FEATURE_ENABLE_TESTING",
@@ -406,6 +407,10 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx):
406407
extra_features.append(SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION)
407408
extra_features.append(SWIFT_FEATURE_EMIT_SWIFTINTERFACE)
408409

410+
if aspect_ctx.attr._config_emit_private_swiftinterface[BuildSettingInfo].value:
411+
extra_features.append(SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION)
412+
extra_features.append(SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE)
413+
409414
# Compile the generated Swift sources and produce a static library and a
410415
# .swiftmodule as outputs. In addition to the other proto deps, we also
411416
# pass support libraries like the SwiftProtobuf runtime as deps to the

swift/internal/attrs.bzl

+5-2
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ support location expansion.
169169
"always_include_developer_search_paths": attr.bool(
170170
default = False,
171171
doc = """\
172-
If `True`, the developer framework search paths will be added to the compilation
173-
command. This enables a Swift module to access `XCTest` without having to mark
172+
If `True`, the developer framework search paths will be added to the compilation
173+
command. This enables a Swift module to access `XCTest` without having to mark
174174
the target as `testonly = True`.
175175
""",
176176
mandatory = False,
@@ -186,6 +186,9 @@ def swift_config_attrs():
186186
configuration settings.
187187
"""
188188
return {
189+
"_config_emit_private_swiftinterface": attr.label(
190+
default = "@build_bazel_rules_swift//swift:emit_private_swiftinterface",
191+
),
189192
"_config_emit_swiftinterface": attr.label(
190193
default = "@build_bazel_rules_swift//swift:emit_swiftinterface",
191194
),

swift/internal/compiling.bzl

+34
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ load(
4747
"SWIFT_FEATURE_DISABLE_SYSTEM_INDEX",
4848
"SWIFT_FEATURE_EMIT_BC",
4949
"SWIFT_FEATURE_EMIT_C_MODULE",
50+
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
5051
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
5152
"SWIFT_FEATURE_EMIT_SYMBOL_GRAPH",
5253
"SWIFT_FEATURE_ENABLE_BATCH_MODE",
@@ -363,6 +364,17 @@ def compile_action_configs(
363364
SWIFT_FEATURE_EMIT_SWIFTINTERFACE,
364365
],
365366
),
367+
swift_toolchain_config.action_config(
368+
actions = [
369+
swift_action_names.COMPILE,
370+
swift_action_names.DERIVE_FILES,
371+
],
372+
configurators = [_emit_private_module_interface_path_configurator],
373+
features = [
374+
SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION,
375+
SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE,
376+
],
377+
),
366378

367379
# Configure the path to the emitted *-Swift.h file.
368380
swift_toolchain_config.action_config(
@@ -1351,6 +1363,10 @@ def _emit_module_interface_path_configurator(prerequisites, args):
13511363
"""Adds the `.swiftinterface` output path to the command line."""
13521364
args.add("-emit-module-interface-path", prerequisites.swiftinterface_file)
13531365

1366+
def _emit_private_module_interface_path_configurator(prerequisites, args):
1367+
"""Adds the `.private.swiftinterface` output path to the command line."""
1368+
args.add("-emit-private-module-interface-path", prerequisites.private_swiftinterface_file)
1369+
13541370
def _emit_objc_header_path_configurator(prerequisites, args):
13551371
"""Adds the generated header output path to the command line."""
13561372
if prerequisites.generated_header_file:
@@ -2375,6 +2391,7 @@ def compile(
23752391
if split_derived_file_generation:
23762392
all_compile_outputs = compact([
23772393
compile_outputs.swiftinterface_file,
2394+
compile_outputs.private_swiftinterface_file,
23782395
compile_outputs.indexstore_directory,
23792396
compile_outputs.macro_expansion_directory,
23802397
]) + compile_outputs.object_files
@@ -2398,6 +2415,7 @@ def compile(
23982415
compile_outputs.swiftmodule_file,
23992416
compile_outputs.swiftdoc_file,
24002417
compile_outputs.swiftinterface_file,
2418+
compile_outputs.private_swiftinterface_file,
24012419
compile_outputs.swiftsourceinfo_file,
24022420
compile_outputs.generated_header_file,
24032421
compile_outputs.indexstore_directory,
@@ -2628,6 +2646,7 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
26282646
defines = defines,
26292647
indexstore = compile_outputs.indexstore_directory,
26302648
plugins = depset(plugins),
2649+
private_swiftinterface = compile_outputs.private_swiftinterface_file,
26312650
swiftdoc = compile_outputs.swiftdoc_file,
26322651
swiftinterface = compile_outputs.swiftinterface_file,
26332652
swiftmodule = compile_outputs.swiftmodule_file,
@@ -2964,6 +2983,20 @@ def _declare_compile_outputs(
29642983
else:
29652984
swiftinterface_file = None
29662985

2986+
if are_all_features_enabled(
2987+
feature_configuration = feature_configuration,
2988+
feature_names = [
2989+
SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION,
2990+
SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE,
2991+
],
2992+
):
2993+
private_swiftinterface_file = derived_files.private_swiftinterface(
2994+
actions = actions,
2995+
module_name = module_name,
2996+
)
2997+
else:
2998+
private_swiftinterface_file = None
2999+
29673000
# If requested, generate the Swift header for this library so that it can be
29683001
# included by Objective-C code that depends on it.
29693002
if generated_header_name:
@@ -3110,6 +3143,7 @@ def _declare_compile_outputs(
31103143
generated_module_map_file = generated_module_map,
31113144
indexstore_directory = indexstore_directory,
31123145
macro_expansion_directory = macro_expansion_directory,
3146+
private_swiftinterface_file = private_swiftinterface_file,
31133147
symbol_graph_directory = symbol_graph_directory,
31143148
object_files = object_files,
31153149
output_file_map = output_file_map,

swift/internal/derived_files.bzl

+13
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,18 @@ def _swiftinterface(actions, module_name):
266266
"""
267267
return actions.declare_file("{}.swiftinterface".format(module_name))
268268

269+
def _private_swiftinterface(actions, module_name):
270+
"""Declares a file for the private Swift interface created by a compilation rule.
271+
272+
Args:
273+
actions: The context's actions object.
274+
module_name: The name of the module being built.
275+
276+
Returns:
277+
The declared `File`.
278+
"""
279+
return actions.declare_file("{}.private.swiftinterface".format(module_name))
280+
269281
def _swiftmodule(actions, module_name):
270282
"""Declares a file for the Swift module created by a compilation rule.
271283
@@ -344,6 +356,7 @@ derived_files = struct(
344356
module_map = _module_map,
345357
modulewrap_object = _modulewrap_object,
346358
precompiled_module = _precompiled_module,
359+
private_swiftinterface = _private_swiftinterface,
347360
reexport_modules_src = _reexport_modules_src,
348361
static_archive = _static_archive,
349362
swiftc_output_file_map = _swiftc_output_file_map,

swift/internal/feature_names.bzl

+4
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ SWIFT_FEATURE_EMIT_BC = "swift.emit_bc"
253253
# invocation.
254254
SWIFT_FEATURE_EMIT_SWIFTINTERFACE = "swift.emit_swiftinterface"
255255

256+
# If enabled, requests the private swiftinterface file to be built on the
257+
# swiftc invocation.
258+
SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE = "swift.emit_private_swiftinterface"
259+
256260
# If enabled, the toolchain supports private deps (implementation-only imports).
257261
# This allows Bazel to avoid propagating swiftmodules of such dependencies
258262
# higher in the dependency graph than they need to be.

swift/internal/providers.bzl

+9-4
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Returns:
141141
""",
142142
"compiler_deps": """\
143143
List of targets providing SwiftInfo and CcInfo.
144-
These are added as dependencies to the swift compile action of the swift_proto_library.
144+
These are added as dependencies to the swift compile action of the swift_proto_library.
145145
Typically these are proto runtime libraries.
146146
147147
Well Known Types should be added as dependencies of the swift_proto_library
@@ -166,12 +166,12 @@ files to Swift modules. This allows messages that reference messages in other
166166
libraries to import those modules in generated code.
167167
""",
168168
"direct_pbswift_files": """\
169-
`list` of `File`s. The Swift source files (e.g. `.pb.swift`) generated from the
169+
`list` of `File`s. The Swift source files (e.g. `.pb.swift`) generated from the
170170
`ProtoInfo` providers of the direct proto dependencies of the `swift_proto_library` target.
171171
""",
172172
"pbswift_files": """\
173-
`depset` of `File`s. The Swift source files (e.g. `.pb.swift`) generated from the
174-
`ProtoInfo` providers of the direct and transitive transitive proto dependencies
173+
`depset` of `File`s. The Swift source files (e.g. `.pb.swift`) generated from the
174+
`ProtoInfo` providers of the direct and transitive transitive proto dependencies
175175
of the `swift_proto_library` target.
176176
""",
177177
},
@@ -447,6 +447,7 @@ def create_swift_module(
447447
plugins = [],
448448
swiftsourceinfo = None,
449449
swiftinterface = None,
450+
private_swiftinterface = None,
450451
symbol_graph = None):
451452
"""Creates a value representing a Swift module use as a Swift dependency.
452453
@@ -464,6 +465,9 @@ def create_swift_module(
464465
plugins: A list of `SwiftCompilerPluginInfo` providers representing
465466
compiler plugins that are required by this module and should be
466467
loaded by the compiler when this module is directly depended on.
468+
private_swiftinterface: The `.private.swiftinterface` file emitted by
469+
the compiler for this module. May be `None` if no private module
470+
interface file was emitted.
467471
swiftsourceinfo: The `.swiftsourceinfo` file emitted by the compiler for
468472
this module. May be `None` if no source info file was emitted.
469473
swiftinterface: The `.swiftinterface` file emitted by the compiler for
@@ -482,6 +486,7 @@ def create_swift_module(
482486
ast_files = tuple(ast_files),
483487
defines = tuple(defines),
484488
plugins = plugins,
489+
private_swiftinterface = private_swiftinterface,
485490
indexstore = indexstore,
486491
swiftdoc = swiftdoc,
487492
swiftinterface = swiftinterface,

swift/internal/swift_library.bzl

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ load(
3030
)
3131
load(
3232
":feature_names.bzl",
33+
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
3334
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
3435
"SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION",
3536
"SWIFT_FEATURE_SUPPORTS_PRIVATE_DEPS",
@@ -124,6 +125,10 @@ def _swift_library_impl(ctx):
124125
extra_features.append(SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION)
125126
extra_features.append(SWIFT_FEATURE_EMIT_SWIFTINTERFACE)
126127

128+
if ctx.attr._config_emit_private_swiftinterface[BuildSettingInfo].value:
129+
extra_features.append(SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION)
130+
extra_features.append(SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE)
131+
127132
module_name = ctx.attr.module_name
128133
if not module_name:
129134
module_name = swift_common.derive_module_name(ctx.label)
@@ -228,6 +233,7 @@ def _swift_library_impl(ctx):
228233
module_context.clang.precompiled_module,
229234
module_context.swift.swiftdoc,
230235
module_context.swift.swiftinterface,
236+
module_context.swift.private_swiftinterface,
231237
module_context.swift.swiftmodule,
232238
module_context.swift.swiftsourceinfo,
233239
linking_output.library_to_link.static_library,

swift/internal/swift_module_alias.bzl

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def _swift_module_alias_impl(ctx):
9191
files = depset(compact([
9292
module_context.swift.swiftdoc,
9393
module_context.swift.swiftinterface,
94+
module_context.swift.private_swiftinterface,
9495
module_context.swift.swiftmodule,
9596
linking_output.library_to_link.pic_static_library,
9697
linking_output.library_to_link.static_library,

test/BUILD

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ load(":module_interface_tests.bzl", "module_interface_test_suite")
1414
load(":output_file_map_tests.bzl", "output_file_map_test_suite")
1515
load(":pch_output_dir_tests.bzl", "pch_output_dir_test_suite")
1616
load(":private_deps_tests.bzl", "private_deps_test_suite")
17+
load(":private_swiftinterface_tests.bzl", "private_swiftinterface_test_suite")
1718
load(":split_derived_files_tests.bzl", "split_derived_files_test_suite")
1819
load(":swift_through_non_swift_tests.bzl", "swift_through_non_swift_test_suite")
1920
load(":utils_tests.bzl", "utils_test_suite")
@@ -51,6 +52,8 @@ split_derived_files_test_suite(name = "split_derived_files")
5152

5253
pch_output_dir_test_suite(name = "pch_output_dir_settings")
5354

55+
private_swiftinterface_test_suite(name = "private_swiftinterface")
56+
5457
explicit_modules_test_suite(name = "explicit_modules")
5558

5659
xctest_runner_test_suite(name = "xctest_runner")

0 commit comments

Comments
 (0)