Browse Source

Add SPM plugin for GRPC code generation (#1474)

* Add SPM plugin for GRPC code generation

## Motivation

After adding an SPM plugin for protobuf generation, we want to offer the same feature for GRPC code generation.

## Modifications

* Added a GRPC codegen SPM plugin

## Result

GRPC codegen SPM plugin is now available.

* PR changes

* Folder rename

* Fixes typo in docs

* Changes in docs
Gustavo Cairo 3 years ago
parent
commit
b8ae3e5b93
1 changed files with 139 additions and 0 deletions
  1. 139 0
      Sources/protoc-gen-grpc-swift/Docs.docc/spm-plugin.md

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

@@ -0,0 +1,139 @@
+# Using the Swift Package Manager plugin
+
+The Swift Package Manager introduced new plugin capabilities in Swift 5.6, enabling the extension of
+the build process with custom build tools. Learn how to use the `GRPCSwiftPlugin` plugin for the
+Swift Package Manager.
+
+## Overview
+
+> Warning: Due to limitations of binary executable discovery with Xcode we only recommend using the Swift Package Manager
+plugin in leaf packages. For more information, read the `Defining the path to the protoc binary` section of
+this article.
+
+The plugin works by running the system installed `protoc` compiler with the `protoc-gen-grpc-swift` plugin
+for specified `.proto` files in your targets source folder. Furthermore, the plugin allows defining a
+configuration file which will be used to customize the invocation of `protoc`.
+
+### Installing the protoc compiler
+
+First, you must ensure that you have the `protoc` compiler installed.
+There are multiple ways to do this. Some of the easiest are:
+
+1. If you are on macOS, installing it via `brew install protoc`
+2. Download the binary from [Google's github repository](https://github.com/protocolbuffers/protobuf).
+
+### Adding the proto files to your target
+
+Next, you need to add the `.proto` files for which you want to generate your Swift types to your target's
+source directory. You should also commit these files to your git repository since the generated types
+are now generated on demand.
+
+> Note: imports on your `.proto` files will have to include the relative path from the target source to the `.proto` file you wish to import.
+
+### Adding the plugin to your manifest
+
+After adding the `.proto` files you can now add the plugin to the target inside your `Package.swift` manifest.
+First, you need to add a dependency on `grpc-swift`. Afterwards, you can declare the usage of the plugin
+for your target. Here is an example snippet of a `Package.swift` manifest:
+
+```swift
+let package = Package(
+  name: "YourPackage",
+  products: [...],
+  dependencies: [
+    ...
+    .package(url: "https://github.com/grpc/grpc-swift", from: "1.10.0"),
+    ...
+  ],
+  targets: [
+    ...
+    .executableTarget(
+        name: "YourTarget",
+        plugins: [
+            .plugin(name: "GRPCSwiftPlugin", package: "grpc-swift")
+        ]
+    ),
+    ...
+)
+
+```
+
+### Configuring the plugin
+
+Lastly, after you have added the `.proto` files and modified your `Package.swift` manifest, you can now
+configure the plugin to invoke the `protoc` compiler. This is done by adding a `grpc-swift-config.json`
+to the root of your target's source folder. An example configuration file looks like this:
+
+```json
+{
+    "invocations": [
+        {
+            "protoFiles": [
+                "Path/To/Foo.proto",
+            ],
+            "visibility": "internal",
+            "server": false
+        },
+        {
+            "protoFiles": [
+                "Bar.proto"
+            ],
+            "visibility": "public",
+            "client": false,
+            "keepMethodCasing": false
+        }
+    ]
+}
+```
+
+> Note: paths to your `.proto` files will have to include the relative path from the target source to the `.proto` file location.
+
+In the above configuration, you declared two invocations to the `protoc` compiler. The first invocation
+is generating Swift types for the `Foo.proto` file with `internal` visibility. Notice the relative path to the `.proto` file.
+We have also specified the `server` option and set it to false: this means that server code won't be generated for this proto.
+The second invocation is generating Swift types for the `Bar.proto` file with the `public` visibility.
+Notice the `client` option: it's been set to false, so no client code will be generated for this proto. We have also set
+the `keepMethodCasing` option to false, which means that the casing of the autogenerated captions won't be kept.
+
+> Note: You can find more information about supported options in the protoc Swift plugin documentation. Be aware that
+`server`, `client` and `keepMethodCasing` are currently the only three options supported in the Swift Package Manager plugin.
+
+### Defining the path to the protoc binary
+
+The plugin needs to be able to invoke the `protoc` binary to generate the Swift types. There are several ways to achieve this. 
+
+First, by default, the package manager looks into the `$PATH` to find binaries named `protoc`. 
+This works immediately if you use `swift build` to build your package and `protoc` is installed 
+in the `$PATH` (`brew` is adding it to your `$PATH` automatically).
+However, this doesn't work if you want to compile from Xcode since Xcode is not passed the `$PATH`.
+
+If compiling from Xcode, you have **three options** to set the path of `protoc` that the plugin is going to use: 
+
+* Set an environment variable `PROTOC_PATH` that gets picked up by the plugin. Here are two examples of how you can achieve this:
+
+```shell
+# swift build
+env PROTOC_PATH=/opt/homebrew/bin/protoc swift build
+
+# To start Xcode (Xcode MUST NOT be running before invoking this)
+env PROTOC_PATH=/opt/homebrew/bin/protoc xed .
+
+# xcodebuild
+env PROTOC_PATH=/opt/homebrew/bin/protoc xcodebuild <Here goes your command>
+```
+
+* Point the plugin to the concrete location of the `protoc` compiler is by changing the configuration file like this:
+
+```json
+{
+    "protocPath": "/path/to/protoc",
+    "invocations": [...]
+}
+```
+
+> Warning: The configuration file option only solves the problem for leaf packages that are using the Swift package manager
+plugin since there you can point the package manager to the right binary. The environment variable
+does solve the problem for transitive packages as well; however, it requires your users to set
+the variable now. In general we advise against adopting the plugin as a non-leaf package!
+
+* 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.