Skip to content

Commit bf6065f

Browse files
authored
Add note about SPM plugin known issues, provide better errors (#1629)
1 parent bf34fdd commit bf6065f

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

Plugins/GRPCSwiftPlugin/plugin.swift

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,27 @@ import PackagePlugin
2020
@main
2121
struct GRPCSwiftPlugin {
2222
/// Errors thrown by the `GRPCSwiftPlugin`
23-
enum PluginError: Error {
23+
enum PluginError: Error, CustomStringConvertible {
2424
/// Indicates that the target where the plugin was applied to was not `SourceModuleTarget`.
25-
case invalidTarget
25+
case invalidTarget(Target)
2626
/// Indicates that the file extension of an input file was not `.proto`.
27-
case invalidInputFileExtension
27+
case invalidInputFileExtension(String)
2828
/// Indicates that there was no configuration file at the required location.
29-
case noConfigFound
29+
case noConfigFound(String)
30+
31+
var description: String {
32+
switch self {
33+
case let .invalidTarget(target):
34+
return "Expected a SwiftSourceModuleTarget but got '\(type(of: target))'."
35+
case let .invalidInputFileExtension(path):
36+
return "The input file '\(path)' does not have a '.proto' extension."
37+
case let .noConfigFound(path):
38+
return """
39+
No configuration file found named '\(path)'. The file must not be listed in the \
40+
'exclude:' argument for the target in Package.swift.
41+
"""
42+
}
43+
}
3044
}
3145

3246
/// The configuration of the plugin.
@@ -88,7 +102,7 @@ struct GRPCSwiftPlugin {
88102
$0.path.lastComponent == Self.configurationFileName
89103
}
90104
)?.path else {
91-
throw PluginError.noConfigFound
105+
throw PluginError.noConfigFound(Self.configurationFileName)
92106
}
93107

94108
let data = try Data(contentsOf: URL(fileURLWithPath: "\(configurationFilePath)"))
@@ -208,7 +222,7 @@ struct GRPCSwiftPlugin {
208222
for invocation in configuration.invocations {
209223
for protoFile in invocation.protoFiles {
210224
if !protoFile.hasSuffix(".proto") {
211-
throw PluginError.invalidInputFileExtension
225+
throw PluginError.invalidInputFileExtension(protoFile)
212226
}
213227
}
214228
}
@@ -221,7 +235,7 @@ extension GRPCSwiftPlugin: BuildToolPlugin {
221235
target: Target
222236
) async throws -> [Command] {
223237
guard let swiftTarget = target as? SwiftSourceModuleTarget else {
224-
throw PluginError.invalidTarget
238+
throw PluginError.invalidTarget(target)
225239
}
226240
return try self.createBuildCommands(
227241
pluginWorkDirectory: context.pluginWorkDirectory,

Sources/protoc-gen-grpc-swift/Docs.docc/spm-plugin.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ Here's an example file structure that looks like this:
5858
```text
5959
Sources
6060
├── main.swift
61-
── ProtoBuf
61+
── ProtoBuf
6262
├── grpc-swift-config.json
6363
├── foo.proto
6464
└── Bar
6565
└── Bar.proto
66-
```
66+
```
6767

6868
```json
6969
{
@@ -103,19 +103,19 @@ the `keepMethodCasing` option to false, which means that the casing of the autog
103103

104104
### Defining the path to the protoc binary
105105

106-
The plugin needs to be able to invoke the `protoc` binary to generate the Swift types. There are several ways to achieve this.
106+
The plugin needs to be able to invoke the `protoc` binary to generate the Swift types. There are several ways to achieve this.
107107

108-
First, by default, the package manager looks into the `$PATH` to find binaries named `protoc`.
109-
This works immediately if you use `swift build` to build your package and `protoc` is installed
108+
First, by default, the package manager looks into the `$PATH` to find binaries named `protoc`.
109+
This works immediately if you use `swift build` to build your package and `protoc` is installed
110110
in the `$PATH` (`brew` is adding it to your `$PATH` automatically).
111111
However, this doesn't work if you want to compile from Xcode since Xcode is not passed the `$PATH`.
112112

113-
If compiling from Xcode, you have **three options** to set the path of `protoc` that the plugin is going to use:
113+
If compiling from Xcode, you have **three options** to set the path of `protoc` that the plugin is going to use:
114114

115115
* Set an environment variable `PROTOC_PATH` that gets picked up by the plugin. Here are two examples of how you can achieve this:
116116

117117
```shell
118-
# swift build
118+
# swift build
119119
env PROTOC_PATH=/opt/homebrew/bin/protoc swift build
120120

121121
# To start Xcode (Xcode MUST NOT be running before invoking this)
@@ -134,9 +134,18 @@ env PROTOC_PATH=/opt/homebrew/bin/protoc xcodebuild <Here goes your command>
134134
}
135135
```
136136

137-
> Warning: The configuration file option only solves the problem for leaf packages that are using the Swift package manager
138-
plugin since there you can point the package manager to the right binary. The environment variable
139-
does solve the problem for transitive packages as well; however, it requires your users to set
140-
the variable now. In general we advise against adopting the plugin as a non-leaf package!
137+
* You can start Xcode by running `$ xed .` from the command line from the directory your project is located - this should make `$PATH` visible to Xcode.
138+
139+
### Known Issues
140+
141+
- The configuration file _must not_ be excluded from the list of sources for the
142+
target in the package manifest (that is, it should not be present in the
143+
`exclude` argument for the target). The build system does not have access to
144+
the file if it is excluded, however, `swift build` will result in a warning
145+
that the file should be excluded.
146+
- The plugin should only be used for leaf package. The configuration file option
147+
only solves the problem for leaf packages that are using the Swift package
148+
manager plugin since there you can point the package manager to the right
149+
binary. The environment variable does solve the problem for transitive
150+
packages as well; however, it requires your users to set the variable now.
141151

142-
* You can start Xcode by running `$ xed .` from the command line from the directory your project is located - this should make `$PATH` visible to Xcode.

0 commit comments

Comments
 (0)