Skip to content

Commit 9bb85e8

Browse files
committed
Add swift_compiler_plugin_group rule
This is similar to `swift_library_group`, in that it allows you to group multiple `swift_compiler_plugin` targets under a single target. This is needed to support SPM’s `plugin` products, which support multiple plugin targets under a single product. Signed-off-by: Brentley Jones <github@brentleyjones.com>
1 parent 90cf746 commit 9bb85e8

19 files changed

+282
-26
lines changed

doc/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ _DOC_SRCS = {
1515
"SwiftInfo",
1616
"SwiftToolchainInfo",
1717
"SwiftProtoCompilerInfo",
18+
"SwiftProtoCompilerCollectionInfo",
1819
"SwiftProtoInfo",
1920
"SwiftUsageInfo",
2021
"DeprecatedSwiftGRPCInfo",
@@ -23,6 +24,7 @@ _DOC_SRCS = {
2324
"swift_binary",
2425
"swift_c_module",
2526
"swift_compiler_plugin",
27+
"swift_compiler_plugin_group",
2628
"universal_swift_compiler_plugin",
2729
"swift_feature_allowlist",
2830
"swift_import",

doc/doc.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ load(
5757
# api
5858
_swift_common = "swift_common",
5959
_swift_compiler_plugin = "swift_compiler_plugin",
60+
_swift_compiler_plugin_group = "swift_compiler_plugin_group",
6061
_swift_feature_allowlist = "swift_feature_allowlist",
6162
_swift_import = "swift_import",
6263
_swift_library = "swift_library",
@@ -90,6 +91,7 @@ deprecated_swift_proto_library = _deprecated_swift_proto_library
9091
swift_binary = _swift_binary
9192
swift_c_module = _swift_c_module
9293
swift_compiler_plugin = _swift_compiler_plugin
94+
swift_compiler_plugin_group = _swift_compiler_plugin_group
9395
universal_swift_compiler_plugin = _universal_swift_compiler_plugin
9496
swift_feature_allowlist = _swift_feature_allowlist
9597
swift_import = _swift_import

doc/rules.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ On this page:
2222
* [swift_binary](#swift_binary)
2323
* [swift_c_module](#swift_c_module)
2424
* [swift_compiler_plugin](#swift_compiler_plugin)
25+
* [swift_compiler_plugin_group](#swift_compiler_plugin_group)
2526
* [universal_swift_compiler_plugin](#universal_swift_compiler_plugin)
2627
* [swift_feature_allowlist](#swift_feature_allowlist)
2728
* [swift_import](#swift_import)
@@ -400,6 +401,25 @@ swift_library(
400401
| <a id="swift_compiler_plugin-swiftc_inputs"></a>swiftc_inputs | Additional files that are referenced using `$(location ...)` in attributes that support location expansion. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
401402

402403

404+
<a id="swift_compiler_plugin_group"></a>
405+
406+
## swift_compiler_plugin_group
407+
408+
<pre>
409+
swift_compiler_plugin_group(<a href="#swift_compiler_plugin_group-name">name</a>, <a href="#swift_compiler_plugin_group-plugins">plugins</a>)
410+
</pre>
411+
412+
413+
414+
**ATTRIBUTES**
415+
416+
417+
| Name | Description | Type | Mandatory | Default |
418+
| :------------- | :------------- | :------------- | :------------- | :------------- |
419+
| <a id="swift_compiler_plugin_group-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
420+
| <a id="swift_compiler_plugin_group-plugins"></a>plugins | A list of `swift_compiler_plugin` or `swift_compiler_plugin_group` targets that should be loaded by the compiler when compiling this module and any modules that directly depend on it. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
421+
422+
403423
<a id="swift_feature_allowlist"></a>
404424

405425
## swift_feature_allowlist
@@ -664,7 +684,7 @@ swift_proto_library(
664684
| <a id="swift_proto_library-additional_compiler_info"></a>additional_compiler_info | Dictionary of additional information passed to the compiler targets. See the documentation of the respective compiler rules for more information on which fields are accepted and how they are used. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
665685
| <a id="swift_proto_library-always_include_developer_search_paths"></a>always_include_developer_search_paths | If `True`, the developer framework search paths will be added to the compilation command. This enables a Swift module to access `XCTest` without having to mark the target as `testonly = True`. | Boolean | optional | `False` |
666686
| <a id="swift_proto_library-alwayslink"></a>alwayslink | If true, any binary that depends (directly or indirectly) on this Swift module will link in all the object files for the files listed in `srcs`, even if some contain no symbols referenced by the binary. This is useful if your code isn't explicitly called by code in the binary; for example, if you rely on runtime checks for protocol conformances added in extensions in the library but do not directly reference any other symbols in the object file that adds that conformance. | Boolean | optional | `False` |
667-
| <a id="swift_proto_library-compilers"></a>compilers | One or more `swift_proto_compiler` targets (or targets producing `SwiftProtoCompilerInfo`), from which the Swift protos will be generated. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `["@build_bazel_rules_swift//proto/compilers:swift_proto"]` |
687+
| <a id="swift_proto_library-compilers"></a>compilers | One or more `swift_proto_compiler` targets (or targets producing `SwiftProtoCompilerInfo`), from which the Swift protos will be generated. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `["@rules_swift//proto/compilers:swift_proto"]` |
668688
| <a id="swift_proto_library-copts"></a>copts | Additional compiler options that should be passed to `swiftc`. These strings are subject to `$(location ...)` and ["Make" variable](https://docs.bazel.build/versions/master/be/make-variables.html) expansion. | List of strings | optional | `[]` |
669689
| <a id="swift_proto_library-defines"></a>defines | A list of defines to add to the compilation command line.<br><br>Note that unlike C-family languages, Swift defines do not have values; they are simply identifiers that are either defined or undefined. So strings in this list should be simple identifiers, **not** `name=value` pairs.<br><br>Each string is prepended with `-D` and added to the command line. Unlike `copts`, these flags are added for the target and every target that depends on it, so use this attribute with caution. It is preferred that you add defines directly to `copts`, only using this feature in the rare case that a library needs to propagate a symbol up to those that depend on it. | List of strings | optional | `[]` |
670690
| <a id="swift_proto_library-generated_header_name"></a>generated_header_name | The name of the generated Objective-C interface header. This name must end with a `.h` extension and cannot contain any path separators.<br><br>If this attribute is not specified, then the default behavior is to name the header `${target_name}-Swift.h`.<br><br>This attribute is ignored if the toolchain does not support generating headers. | String | optional | `""` |
@@ -801,6 +821,6 @@ swift_library(
801821
| Name | Description | Type | Mandatory | Default |
802822
| :------------- | :------------- | :------------- | :------------- | :------------- |
803823
| <a id="universal_swift_compiler_plugin-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
804-
| <a id="universal_swift_compiler_plugin-plugin"></a>plugin | Target to generate a 'fat' binary from. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
824+
| <a id="universal_swift_compiler_plugin-plugin"></a>plugin | A `swift_compiler_plugin` target to generate a 'fat' binary for. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
805825

806826

examples/xplatform/macros/BUILD

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
load("//swift:swift.bzl", "swift_binary", "swift_library", "swift_test")
2-
load("//swift:swift_compiler_plugin.bzl", "swift_compiler_plugin", "universal_swift_compiler_plugin")
2+
load(
3+
"//swift:swift_compiler_plugin.bzl",
4+
"swift_compiler_plugin",
5+
"swift_compiler_plugin_group",
6+
"universal_swift_compiler_plugin",
7+
)
38

49
licenses(["notice"])
510

@@ -12,14 +17,19 @@ swift_library(
1217
name = "stringify",
1318
srcs = ["Stringify.swift"],
1419
module_name = "Stringify",
15-
plugins = [":stringify_macro"],
20+
plugins = [":stringify_macro_group"],
1621
)
1722

1823
swift_library(
1924
name = "stringify_universal",
2025
srcs = ["Stringify.swift"],
2126
module_name = "StringifyUniversal",
22-
plugins = [":stringify_macro_universal"],
27+
plugins = [
28+
# We don't create and use a `stringify_macro_universal` here, but we
29+
# could have if we wanted to
30+
":stringify_macro_universal",
31+
":stringify2_macro_universal",
32+
],
2333
)
2434

2535
swift_compiler_plugin(
@@ -41,11 +51,43 @@ swift_compiler_plugin(
4151
],
4252
)
4353

54+
swift_compiler_plugin(
55+
name = "stringify2_macro",
56+
srcs = [
57+
"Stringify2Macro.swift",
58+
"Stringify2MacroPlugin.swift",
59+
],
60+
module_name = "Stringify2MacroPlugin",
61+
target_compatible_with = select({
62+
":supports_macros": [],
63+
"//conditions:default": ["@platforms//:incompatible"],
64+
}),
65+
deps = [
66+
"@SwiftSyntax",
67+
"@SwiftSyntax//:SwiftCompilerPlugin",
68+
"@SwiftSyntax//:SwiftSyntaxBuilder",
69+
"@SwiftSyntax//:SwiftSyntaxMacros",
70+
],
71+
)
72+
73+
swift_compiler_plugin_group(
74+
name = "stringify_macro_group",
75+
plugins = [
76+
":stringify_macro",
77+
":stringify2_macro",
78+
],
79+
)
80+
4481
universal_swift_compiler_plugin(
4582
name = "stringify_macro_universal",
4683
plugin = ":stringify_macro",
4784
)
4885

86+
universal_swift_compiler_plugin(
87+
name = "stringify2_macro_universal",
88+
plugin = ":stringify_macro",
89+
)
90+
4991
swift_binary(
5092
name = "stringify_client",
5193
srcs = ["StringifyClient.swift"],
@@ -66,6 +108,9 @@ swift_test(
66108
"//conditions:default": ["@platforms//:incompatible"],
67109
}),
68110
deps = [
111+
":stringify_macro_group",
112+
# `stringify_macro` is in `stringify_macro_group`, but we list both to
113+
# show that it handles that fine
69114
":stringify_macro",
70115
"@SwiftSyntax",
71116
"@SwiftSyntax//:SwiftSyntaxBuilder",

examples/xplatform/macros/Stringify.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@
1515
@freestanding(expression)
1616
public macro stringify<T>(_ value: T) -> (T, String) =
1717
#externalMacro(module: "StringifyMacroPlugin", type: "StringifyMacro")
18+
19+
@freestanding(expression)
20+
public macro stringify2<T>(_ value: T) -> (T, String) =
21+
#externalMacro(module: "Stringify2MacroPlugin", type: "Stringify2Macro")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2023 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+
import SwiftSyntax
16+
import SwiftSyntaxBuilder
17+
import SwiftSyntaxMacros
18+
19+
public struct Stringify2Macro: ExpressionMacro {
20+
public static func expansion(
21+
of node: some FreestandingMacroExpansionSyntax,
22+
in context: some MacroExpansionContext
23+
) -> ExprSyntax {
24+
guard let argument = node.argumentList.first?.expression else {
25+
fatalError("compiler bug: the macro does not have any arguments")
26+
}
27+
return "(\(argument), \(literal: argument.description))"
28+
}
29+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 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+
#if canImport(SwiftCompilerPlugin)
16+
import SwiftCompilerPlugin
17+
import SwiftSyntaxMacros
18+
19+
@main
20+
struct Stringify2MacroPlugin: CompilerPlugin {
21+
let providingMacros: [Macro.Type] = [
22+
Stringify2Macro.self
23+
]
24+
}
25+
#endif

examples/xplatform/macros/StringifyClient.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ import Stringify
1818
struct Main {
1919
static func main() {
2020
print(#stringify(1 + 2))
21+
print(#stringify2(2 + 1))
2122
}
2223
}

examples/xplatform/macros/StringifyMacroTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import SwiftSyntax
1616
import SwiftSyntaxBuilder
1717
import SwiftSyntaxMacros
1818
import StringifyMacroPlugin
19+
import Stringify2MacroPlugin
1920
import XCTest
2021

2122
class StringifyMacroTests: XCTestCase {
@@ -35,4 +36,21 @@ class StringifyMacroTests: XCTestCase {
3536
"""#
3637
)
3738
}
39+
40+
func testStringify2() {
41+
let sourceFile: SourceFileSyntax = #"""
42+
_ = #stringify2(2 + 1)
43+
"""#
44+
let context = BasicMacroExpansionContext(
45+
sourceFiles: [sourceFile: .init(moduleName: "TestModule", fullFilePath: "Test.swift")]
46+
)
47+
let transformedSourceFile =
48+
sourceFile.expand(macros: ["stringify2": Stringify2Macro.self], in: context)
49+
XCTAssertEqual(
50+
String(describing: transformedSourceFile),
51+
#"""
52+
_ = (2 + 1, "2 + 1")
53+
"""#
54+
)
55+
}
3856
}

swift/deprecated_proto/deprecated_swift_grpc_library.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def _register_grpcswift_generate_action(
222222
return generated_files
223223

224224
def _swift_grpc_library_impl(ctx):
225-
print("WARNING: This rule is deprecated. See [the proto migration doc](proto_migration.md) for more information.") # buildifier: disable=print
225+
print("WARNING: This rule is deprecated. See proto_migration.md for more information.") # buildifier: disable=print
226226

227227
if len(ctx.attr.deps) != 1:
228228
fail(

0 commit comments

Comments
 (0)