Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
version: 1
builder:
configs:
- documentation_targets: [GRPC, GRPCReflectionService, protoc-gen-grpc-swift, GRPCCore]
- documentation_targets: [GRPCCore, GRPCCodeGen]
swift_version: 6.0
- documentation_targets: [GRPCInProcessTransport]
swift_version: 6.0
# Don't include @_exported types from GRPCCore
custom_documentation_parameters: [--exclude-extended-types]
67 changes: 42 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
# gRPC Swift

This repository contains a gRPC code generator and runtime libraries for Swift.
You can read more about gRPC on the [gRPC project's website][grpcio].

## Versions

gRPC Swift is currently undergoing active development to take full advantage of
Swift's native concurrency features. The culmination of this work will be a new
major version, v2.x. Pre-release versions will be available in the near future.

In the meantime, v1.x is available and still supported. You can read more about
it on the [Swift Package Index][spi-grpc-swift-main].

## Security

Please see [SECURITY.md](SECURITY.md).

## License

gRPC Swift is released under the same license as [gRPC][gh-grpc], repeated in
[LICENSE](LICENSE).

## Contributing

Please get involved! See our [guidelines for contributing](CONTRIBUTING.md).
This repository contains a gRPC implementation for Swift. You can read more
about gRPC on the [gRPC project's website][grpcio].

> gRPC Swift v2.x is under active development on the `main` branch and takes
> full advantage of Swift's native concurrency features.
>
> v1.x is still supported and maintained on the `release/1.x` branch.

- 📚 **Documentation** and **tutorials** are available on the [Swift Package Index][spi-grpc-swift]
- 💻 **Examples** are available in the [Examples](Examples) directory
- 🚀 **Contributions** are welcome, please see [CONTRIBUTING.md](CONTRIBUTING.md)
- 🪪 **License** is Apache 2.0, repeated in [LICENSE](License)
- 🔒 **Security** issues should be reported via the process in [SECURITY.md](SECURITY.md)

## Quick Start
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe link to the hello world tutorial from the Quick Start section, maybe below the Package.swift? I'm thinking, someone may come in wanting to play with this, copy the manifest, and then might struggle a bit clicking around documentations on SPI. Having the link to the tutorial directly may make things slightly easier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's a good point. I'd like the README to remain really focused by just having the bullet points (the manifest is the exception because it's easy to copy and paste). What if we add a "Tutorials" bullet to the list above between Documentation and Examples?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up just mentioning tutorials in the documentation point above as they link to the same place.


The following snippet contains a Swift Package manifest to use gRPC Swift v2.x with
the SwiftNIO based transport and SwiftProtobuf serialization:

```swift
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
name: "foo-package",
platforms: [.macOS("15.0")],
dependencies: [
.package(url: "https://github.com/grpc/grpc-swift-nio-transport.git", from: "1.0.0-alpha.1"),
.package(url: "https://github.com/grpc/grpc-swift-protobuf.git", from: "1.0.0-alpha.1"),
],
targets: [
.executableTarget(
name: "bar-target",
dependencies: [
.product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"),
.product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"),
]
)
]
)
```

[gh-grpc]: https://github.com/grpc/grpc
[grpcio]: https://grpc.io
[spi-grpc-swift-main]: https://swiftpackageindex.com/grpc/grpc-swift/main/documentation/grpccore
[spi-grpc-swift]: https://swiftpackageindex.com/grpc/grpc-swift/documentation
4 changes: 1 addition & 3 deletions Sources/GRPCCore/Call/Server/ServerInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@
///
/// Interceptors are registered with the server apply to all RPCs. If you need to modify the
/// behavior of an interceptor on a per-RPC basis then you can use the
/// ``ServerInterceptorContext/descriptor`` to determine which RPC is being called and
/// ``ServerContext/descriptor`` to determine which RPC is being called and
/// conditionalise behavior accordingly.
///
/// - TODO: Update example and documentation to show how to register an interceptor.
///
/// ## RPC filtering
///
/// A common use of server-side interceptors is to filter requests from clients. Interceptors can
Expand Down
137 changes: 8 additions & 129 deletions Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,129 +2,14 @@

Learn how to generate stubs for gRPC Swift from a service defined using the Protocol Buffers IDL.

## Overview

There are two approaches to generating stubs from Protocol Buffers:

1. With the Swift Package Manager build plugin, or
2. With the Protocol Buffers compiler (`protoc`).

The following sections describe how and when to use each.

### Using the Swift Package Manager build plugin

You can generate stubs at build time by using `GRPCSwiftPlugin` which is a build plugin for the
Swift Package Manager. Using it means that you don't have to manage the generation of
stubs with separate tooling, or check the generated stubs into your source repository.

The build plugin will generate gRPC stubs for you by building `protoc-gen-grpc-swift` (more details
in the following section) for you and invoking `protoc`. Because of the implicit
dependency on `protoc` being made available by the system `GRPCSwiftPlugin` isn't suitable for use
in:

- Library packages, or
- Environments where `protoc` isn't available.

> `GRPCSwiftPlugin` _only_ generates gRPC stubs, it doesn't generate messages. You must generate
> messages in addition to the gRPC Stubs. The [Swift Protobuf](https://github.com/apple/swift-protobuf)
> project provides an equivalent build plugin, `SwiftProtobufPlugin`, for this.

#### Configuring the build plugin

You can configure which stubs `GRPCSwiftPlugin` generates and how via a configuration file. This
must be called `grpc-swift-config.json` and can be placed anywhere in the source directory for your
target.

A config file for the plugin is made up of a number of `protoc` invocations. Each invocation
describes the inputs to `protoc` as well as any options.

The following is a list of options which can be applied to each invocation object:
- `protoFiles`, an array of strings where each string is the path to an input `.proto` file
_relative to `grpc-swift-config.json`_.
- `visibility`, a string describing the access level of the generated stub (must be one
of `"public"`, `"internal"`, or `"package"`). If not specified then stubs are generated as
`internal`.
- `server`, a boolean indicating whether server stubs should be generated. Defaults to `true` if
not specified.
- `client`, a boolean indicating whether client stubs should be generated. Defaults to `true` if
not specified.
- `_V2`, a boolean indicated whether the generated stubs should be for v2.x. Defaults to `false` if
not specified.

> The `GRPCSwiftPlugin` build plugin is currently shared between gRPC Swift v1.x and v2.x. To
> generate stubs for v2.x you _must_ set `_V2` to `true` in your config.
>
> This option will be deprecated and removed once v2.x has been released.

#### Finding protoc

The build plugin requires a copy of the `protoc` binary to be available. To resolve which copy of
the binary to use, `GRPCSwiftPlugin` will look at the following in order:

1. The exact path specified in the `protocPath` property in `grpc-swift-config.json`, if present.
2. The exact path specified in the `PROTOC_PATH` environment variable, if set.
3. The first `protoc` binary found in your `PATH` environment variable.

#### Using the build plugin from Xcode

Xcode doesn't have access to your `PATH` so in order to use `GRPCSwiftPlugin` with Xcode you must
either set `protocPath` in your `grpc-swift-config.json` or explicitly set `PROTOC_PATH` when
opening Xcode.

You can do this by running:

```sh
env PROTOC_PATH=/path/to/protoc xed /path/to/your-project
```

Note that Xcode must _not_ be open before running this command.

#### Example configuration

We recommend putting your config and `.proto` files in a directory called `Protos` within your
target. Here's an example package structure:

```
MyPackage
├── Package.swift
└── Sources
└── MyTarget
└── Protos
├── foo
│   └── bar
│   ├── baz.proto
│   └── buzz.proto
└── grpc-swift-config.json
```

If you wanted the generated stubs from `baz.proto` to be `public`, and to only generate a client
for `buzz.proto` then the `grpc-swift-config` could look like this:

```json
{
"invocations": [
{
"_V2": true,
"protoFiles": ["foo/bar/baz.proto"],
"visibility": "public"
},
{
"_V2": true,
"protoFiles": ["foo/bar/buzz.proto"],
"server": false
}
]
}
```

### Using protoc
## Using protoc

If you've used Protocol Buffers before then generating gRPC Swift stubs should be simple. If you're
unfamiliar with Protocol Buffers then you should get comfortable with the concepts before
continuing; the [Protocol Buffers website](https://protobuf.dev/) is a great place to start.

gRPC Swift provides `protoc-gen-grpc-swift`, a program which is a plugin for the Protocol Buffers
compiler, `protoc`.
The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package provides
`protoc-gen-grpc-swift`, a program which is a plugin for the Protocol Buffers compiler, `protoc`.

> `protoc-gen-grpc-swift` only generates gRPC stubs, it doesn't generate messages. You must use
> `protoc-gen-swift` to generate messages in addition to gRPC Stubs.
Expand Down Expand Up @@ -160,22 +45,16 @@ protoc \
--grpc-swift_out=.
```

#### Generator options
### Generator options

| Name | Possible Values | Default | Description |
|---------------------------|--------------------------------------------|------------|----------------------------------------------------------|
| `_V2` | `True`, `False` | `False` | Whether stubs are generated for gRPC Swift v2.x |
| `Visibility` | `Public`, `Package`, `Internal` | `Internal` | Access level for generated stubs |
| `Server` | `True`, `False` | `True` | Generate server stubs |
| `Client` | `True`, `False` | `True` | Generate client stubs |
| `FileNaming` | `FullPath`, `PathToUnderscore`, `DropPath` | `FullPath` | How generated source files should be named. (See below.) |
| `ProtoPathModuleMappings` | | | Path to module map `.asciipb` file. (See below.) |
| `AccessLevelOnImports` | `True`, `False` | `True` | Whether imports should have explicit access levels. |

> The `protoc-gen-grpc-swift` binary is currently shared between gRPC Swift v1.x and v2.x. To
> generate stubs for v2.x you _must_ specify `_V2=True`.
>
> This option will be deprecated and removed once v2.x has been released.
| `UseAccessLevelOnImports` | `True`, `False` | `False` | Whether imports should have explicit access levels. |

The `FileNaming` option has three possible values, for an input of `foo/bar/baz.proto` the following
output file will be generated:
Expand All @@ -188,12 +67,12 @@ allows you to specify a mapping from `.proto` files to the Swift module they are
allows the code generator to add appropriate imports to your generated stubs. This is described in
more detail in the [SwiftProtobuf documentation](https://github.com/apple/swift-protobuf/blob/main/Documentation/PLUGIN.md).

#### Building the plugin
### Building the plugin

> The version of `protoc-gen-grpc-swift` you use mustn't be newer than the version of
> the `grpc-swift` you're using.
> the `grpc-swift-protobuf` you're using.

If your package depends on `grpc-swift` then you can get a copy of `protoc-gen-grpc-swift`
If your package depends on `grpc-swift-protobuf` then you can get a copy of `protoc-gen-grpc-swift`
by building it directly:

```console
Expand Down
43 changes: 32 additions & 11 deletions Sources/GRPCCore/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,38 @@ A gRPC library for Swift written natively in Swift.

## Package structure

gRPC Swift is made up of a number of modules, each of which is documented separately. However this
module – ``GRPCCore`` – includes higher level documentation such as tutorials. The following list
contains products of this package:

- ``GRPCCore`` contains core types and abstractions and is the 'base' module for the project.
- `GRPCInProcessTransport` contains an implementation of an in-process transport.
- `GRPCHTTP2TransportNIOPosix` provides client and server implementations of HTTP/2 transports built
on top of SwiftNIO's POSIX Sockets abstractions.
- `GRPCHTTP2TransportNIOTransportServices` provides client and server implementations of HTTP/2
transports built on top of SwiftNIO's Network.framework abstraction, `NIOTransportServices`.
- `GRPCProtobuf` provides serialization and deserialization components for `SwiftProtobuf`.
gRPC Swift is distributed across multiple Swift packages. These are:

- `grpc-swift` (this package) containing core gRPC abstractions and an in-process transport.
- GitHub repository: [`grpc/grpc-swift`](https://github.com/grpc/grpc-swift)
- Documentation: hosted on the [Swift Package
Index](https://swiftpackageindex.com/grpc/grpc-swift/documentation)
- `grpc-swift-nio-transport` contains high-performance HTTP/2 transports built on top
of [SwiftNIO](https://github.com/apple/swift-nio).
- GitHub repository: [`grpc/grpc-swift-nio-transport`](https://github.com/grpc/grpc-swift-nio-transport)
- Documentation: hosted on the [Swift Package
Index](https://swiftpackageindex.com/grpc/grpc-swift-nio-transport/documentation)
- `grpc-swift-protobuf` contains runtime serialization components to interoperate with
[SwiftProtobuf](https://github.com/apple/swift-protobuf) as well as a plugin for the Protocol
Buffers compiler, `protoc`.
- GitHub repository: [`grpc/grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf)
- Documentation: hosted on the [Swift Package
Index](https://swiftpackageindex.com/grpc/grpc-swift-protobuf/documentation)
- `grpc-swift-extras` contains optional runtime components and integrations with other packages.
- GitHub repository: [`grpc/grpc-swift-extras`](https://github.com/grpc/grpc-swift-extras)
- Documentation: hosted on the [Swift Package
Index](https://swiftpackageindex.com/grpc/grpc-swift-extras/documentation)

This package, and this module (``GRPCCore``) in particular, include higher level documentation such
as tutorials.

## Modules in this package

- ``GRPCCore`` (this module) contains core abstractions, currency types and runtime components
for gRPC Swift.
- `GRPCInProcessTransport` contains an in-process implementation of the ``ClientTransport`` and
``ServerTransport`` protocols.
- `GRPCodeGen` contains components for building a code generator.

## Topics

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
git clone https://github.com/grpc/grpc-swift
```

The rest of the tutorial assumes that your current working directory is the cloned `grpc-swift`
directory.
You then need to change directory to the `Examples/hello-world` directory of the cloned
repository. The rest of the tutorial assumes this is the current working directory.
}

@Section(title: "Run a gRPC application") {
Expand Down Expand Up @@ -60,8 +60,7 @@

@Steps {
@Step {
Open `HelloWorld.proto` in the `Examples/v2/hello-world` directory to see how the
service is defined.
Open `HelloWorld.proto` in to see how the service is defined.

@Code(name: "HelloWorld.proto", file: "hello-world-sec03-step01.proto")
}
Expand All @@ -77,10 +76,10 @@

@Section(title: "Update and run the application") {
You need to regenerate the stubs as the service definition has changed. To do this run the
following command from the root of the checked out repository:
following command from the _root of the checked out repository_:

```console
Protos/generate.sh
dev/protos/generate.sh
```

To learn how to generate stubs check out the <doc:Generating-stubs> article.
Expand All @@ -90,7 +89,7 @@

@Steps {
@Step {
Open `Serve.swift` in the `Examples/v2/hello-world/Subcommands` directory.
Open `Serve.swift` in the `Subcommands` directory.

@Code(name: "Serve.swift", file: "hello-world-sec04-step01.swift")
}
Expand All @@ -102,8 +101,7 @@
}

@Step {
Let's update the client now. Open `Greet.swift` in the
`Examples/v2/hello-world/Subcommands` directory.
Let's update the client now. Open `Greet.swift` in the `Subcommands` directory.

@Code(name: "Greet.swift", file: "hello-world-sec04-step03.swift")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
struct Greeter: Helloworld_GreeterServiceProtocol {
func sayHello(
request: ServerRequest.Single<Helloworld_HelloRequest>
request: ServerRequest.Single<Helloworld_HelloRequest>,
context: ServerContext
) async throws -> ServerResponse.Single<Helloworld_HelloReply> {
var reply = Helloworld_HelloReply()
let recipient = request.message.name.isEmpty ? "stranger" : request.message.name
Expand Down
Loading
Loading