From 6cb362ce06b22493cdb76999f603a57537d8eea1 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Thu, 23 Jan 2025 17:25:41 +0000 Subject: [PATCH 1/8] Document use of the build plugin Motivation: To ease use of the `grpc-swift-protobuf` Swift Package Manager build plugin. Modifications: Documentation added. Result: Greater understanding? --- .../Articles/Generating-stubs.md | 96 ++++++++++++++++++- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 80c983184..40d230726 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -4,8 +4,6 @@ Learn how to generate stubs for gRPC Swift from a service defined using the Prot ## Overview -### 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. @@ -16,7 +14,17 @@ The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package > `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. -To generate gRPC stubs for your `.proto` files you must run the `protoc` command with +The protoc plugin can be used from the command line directly, passed to `protoc`, or +you can make use of a convenience which adds the stub generation to the Swift build graph. +The automatic gRPC Swift stub generation makes use of a [Swift Package Manager build plugin]( +https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) to use the +`.proto` files as inputs to the build graph, input them into `protoc` using `protoc-gen-grpc-swift` +and `protoc-gen-swift` as needed, and make the resulting gRPC Swift stubs available to code +against without committing them as source. The build plugin may be invoked either from the command line or from Xcode. + +### Using protoc + +To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with the `--grpc-swift_out=` option: ```console @@ -69,7 +77,7 @@ 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 protoc plugin > The version of `protoc-gen-grpc-swift` you use mustn't be newer than the version of > the `grpc-swift-protobuf` you're using. @@ -83,3 +91,83 @@ swift build --product protoc-gen-grpc-swift This command will build the plugin into `.build/debug` directory. You can get the full path using `swift build --show-bin-path`. + +## Using the build plugin + +The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. +Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be guaranteed +to be available at compile time. Also because of a limitation of Swift Package Manager build plugins, the plugin +will only be invoked when applied to the source contained in a leaf package, so it is not useful for generating code for +library authors. + +The build plugin will detect `.proto` files in the source tree and perform one invocation of `protoc` for each file +(caching results and performing the generation as necessary). + +### Adoption +Swift Package Manager build plugins must be adopted on a per-target basis, you can do this by modifying your +package manifest (`Package.swift` file). You will need to declare the `grpc-swift-protobuf` package as a package +dependency and then add the plugin to any desired targets. + +For example, to make use of the plugin for generating gRPC Swift stubs as part of the +`plugin-adopter` target: +```swift +targets: [ + .executableTarget( + name: "plugin-adopter", + dependencies: [ + // ... + ], + plugins: [ + .plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") + ] + ) + ] +``` +Once this is done you need to ensure that that the `.proto` files to be used for generation +are included in the target's source directory (below relevant the `Source` directory) and that you have +defined at least one configuration file. + +### Configuration + +The build plugin requires a configuration file to be present in a directory which encloses all `.proto` files +(in the same directory or a parent). +Configuration files are JSON which tells the build plugin about the options which will be used in the +invocations of `protoc`. Configuration files must be named `grpc-swift-proto-generator-config.json` +and have the following format: +```json +{ + "generate": { + "clients": true, + "servers": true, + "messages": true, + }, + "generatedSource": { + "accessLevelOnImports": false, + "accessLevel": "internal", + } + "protoc": { + "executablePath": "/opt/homebrew/bin/protoc" + "importPaths": [ + "../directory_1", + ], + }, +} +``` + +The options do not need to be specified and each have default values. + +| Name | Possible Values | Default | Description | +|----------------------------------------|--------------------------------------------|--------------------------------------|----------------------------------------------------------| +| `generate.servers` | `true`, `false` | `True` | Generate server stubs | +| `generate.clients` | `true`, `false` | `True` | Generate client stubs | +| `generate.messages` | `true`, `false` | `True` | Generate message stubs | +| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | +| `generatedSource.accessLevel` | `public`, `package`, `internal` | `internal` | Access level for generated stubs | +| `protoc.executablePath` | N/A | N/A (attempted discovery) | Path to the `protoc` executable | +| `protoc.importPaths` | N/A | Directory containing the config file | Access level for generated stubs | + +Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. + +If you require greater flexibility you may specify more than one configuration file. +Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file +lower in the file hierarchy supersedes one above it. From 9e70d5c6f243826f8e6a15c3fa490eae2ec7a625 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 11:26:12 +0000 Subject: [PATCH 2/8] review comments --- .../Articles/Generating-stubs.md | 174 +++++++++--------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 40d230726..84ca3b6e0 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -11,16 +11,96 @@ continuing; the [Protocol Buffers website](https://protobuf.dev/) is a great pla 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`. +You can use the protoc plugin from the command line directly, or you can make use of a + [Swift Package Manager build plugin](https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) +convenience which adds the stub generation to the Swift build graph. +You may use the build plugin either from the command line or from Xcode. + + > `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. -The protoc plugin can be used from the command line directly, passed to `protoc`, or -you can make use of a convenience which adds the stub generation to the Swift build graph. -The automatic gRPC Swift stub generation makes use of a [Swift Package Manager build plugin]( -https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) to use the -`.proto` files as inputs to the build graph, input them into `protoc` using `protoc-gen-grpc-swift` -and `protoc-gen-swift` as needed, and make the resulting gRPC Swift stubs available to code -against without committing them as source. The build plugin may be invoked either from the command line or from Xcode. + + +## Using the build plugin + +The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. +Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be available +at compile time. This requirements means it is not a good fit for library authors who do not have +direct control over this. + +The build plugin detects `.proto` files in the source tree and invokes `protoc` once for each file +(caching results and performing the generation as necessary). + +### Adoption +You must adopt Swift Package Manager build plugins on a per-target basis by modifying your package manifest +(`Package.swift` file). To do this, declare the grpc-swift-protobuf package as a dependency and add the plugin +to your desired targets. + +For example, to make use of the plugin for generating gRPC Swift stubs as part of the +`echo-server` target: +```swift +targets: [ + .executableTarget( + name: "echo-server", + dependencies: [ + // ... + ], + plugins: [ + .plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") + ] + ) + ] +``` +Once this is done you need to ensure that that the `.proto` files to be used for generation +are included in the target's source directory and that you have defined at least one configuration file. + +### Configuration + +You must provide a configuration file in the directory which encloses all .proto files (in the same directory or a parent). +Configuration files, written in JSON, tell the build plugin about the options used for protoc invocations. +You must name the file grpc-swift-proto-generator-config.json and structure it in the following format: +```json +{ + "generate": { + "clients": true, + "servers": true, + "messages": true, + }, + "generatedSource": { + "accessLevelOnImports": false, + "accessLevel": "internal", + } + "protoc": { + "executablePath": "/opt/homebrew/bin/protoc" + "importPaths": [ + "../directory_1", + ], + }, +} +``` + +The options do not need to be specified and each have default values. + +| Name | Possible Values | Default | Description | +|----------------------------------------|--------------------------------------------|--------------|-----------------------------------------------------| +| `generate.servers` | `true`, `false` | `true` | Generate server stubs | +| `generate.clients` | `true`, `false` | `true` | Generate client stubs | +| `generate.messages` | `true`, `false` | `true` | Generate message stubs | +| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | +| `generatedSource.accessLevel` | `"public"`, `"package"`, `"internal"` | `"internal"` | Access level for generated stubs | +| `protoc.executablePath` | N/A | null† | Path to the `protoc` executable | +| `protoc.importPaths` | N/A | null‡ | Import paths passed to `protoc` | + +† The Swift Package Manager build plugin infrastructure will attempt to discover the executable's location if you don't provide one. + +‡ If you don't provide any import paths then the path to the configuration file will be used on a per-source-file basis. + +Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. + +If you require greater flexibility you may specify more than one configuration file. +Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file +lower in the file hierarchy supersedes one above it. ### Using protoc @@ -91,83 +171,3 @@ swift build --product protoc-gen-grpc-swift This command will build the plugin into `.build/debug` directory. You can get the full path using `swift build --show-bin-path`. - -## Using the build plugin - -The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. -Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be guaranteed -to be available at compile time. Also because of a limitation of Swift Package Manager build plugins, the plugin -will only be invoked when applied to the source contained in a leaf package, so it is not useful for generating code for -library authors. - -The build plugin will detect `.proto` files in the source tree and perform one invocation of `protoc` for each file -(caching results and performing the generation as necessary). - -### Adoption -Swift Package Manager build plugins must be adopted on a per-target basis, you can do this by modifying your -package manifest (`Package.swift` file). You will need to declare the `grpc-swift-protobuf` package as a package -dependency and then add the plugin to any desired targets. - -For example, to make use of the plugin for generating gRPC Swift stubs as part of the -`plugin-adopter` target: -```swift -targets: [ - .executableTarget( - name: "plugin-adopter", - dependencies: [ - // ... - ], - plugins: [ - .plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") - ] - ) - ] -``` -Once this is done you need to ensure that that the `.proto` files to be used for generation -are included in the target's source directory (below relevant the `Source` directory) and that you have -defined at least one configuration file. - -### Configuration - -The build plugin requires a configuration file to be present in a directory which encloses all `.proto` files -(in the same directory or a parent). -Configuration files are JSON which tells the build plugin about the options which will be used in the -invocations of `protoc`. Configuration files must be named `grpc-swift-proto-generator-config.json` -and have the following format: -```json -{ - "generate": { - "clients": true, - "servers": true, - "messages": true, - }, - "generatedSource": { - "accessLevelOnImports": false, - "accessLevel": "internal", - } - "protoc": { - "executablePath": "/opt/homebrew/bin/protoc" - "importPaths": [ - "../directory_1", - ], - }, -} -``` - -The options do not need to be specified and each have default values. - -| Name | Possible Values | Default | Description | -|----------------------------------------|--------------------------------------------|--------------------------------------|----------------------------------------------------------| -| `generate.servers` | `true`, `false` | `True` | Generate server stubs | -| `generate.clients` | `true`, `false` | `True` | Generate client stubs | -| `generate.messages` | `true`, `false` | `True` | Generate message stubs | -| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | -| `generatedSource.accessLevel` | `public`, `package`, `internal` | `internal` | Access level for generated stubs | -| `protoc.executablePath` | N/A | N/A (attempted discovery) | Path to the `protoc` executable | -| `protoc.importPaths` | N/A | Directory containing the config file | Access level for generated stubs | - -Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. - -If you require greater flexibility you may specify more than one configuration file. -Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file -lower in the file hierarchy supersedes one above it. From 299f6b87decc35fefa3db5d2b9ed2cee23d2d565 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 13:28:52 +0000 Subject: [PATCH 3/8] Update Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md Co-authored-by: George Barnett --- .../GRPCCore/Documentation.docc/Articles/Generating-stubs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 84ca3b6e0..adb4fa105 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -57,7 +57,7 @@ are included in the target's source directory and that you have defined at least ### Configuration -You must provide a configuration file in the directory which encloses all .proto files (in the same directory or a parent). +You must provide a configuration file in the directory which encloses all `.proto` files (in the same directory or a parent). Configuration files, written in JSON, tell the build plugin about the options used for protoc invocations. You must name the file grpc-swift-proto-generator-config.json and structure it in the following format: ```json From 9b9c1ad980efdc81147cf47266d3acdb1f744b1a Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 13:29:12 +0000 Subject: [PATCH 4/8] Update Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md Co-authored-by: George Barnett --- .../GRPCCore/Documentation.docc/Articles/Generating-stubs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index adb4fa105..1b6e2f6a1 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -96,7 +96,7 @@ The options do not need to be specified and each have default values. ‡ If you don't provide any import paths then the path to the configuration file will be used on a per-source-file basis. -Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. +Many of these options map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. If you require greater flexibility you may specify more than one configuration file. Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file From 3d2e22939bf9741a26bc1c3235bc9634db98dc06 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 13:29:27 +0000 Subject: [PATCH 5/8] Update Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md Co-authored-by: George Barnett --- .../GRPCCore/Documentation.docc/Articles/Generating-stubs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 1b6e2f6a1..f49bcf33e 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -58,7 +58,7 @@ are included in the target's source directory and that you have defined at least ### Configuration You must provide a configuration file in the directory which encloses all `.proto` files (in the same directory or a parent). -Configuration files, written in JSON, tell the build plugin about the options used for protoc invocations. +Configuration files, written in JSON, tell the build plugin about the options used for `protoc` invocations. You must name the file grpc-swift-proto-generator-config.json and structure it in the following format: ```json { From 5a33c78d3682a0af8d5e37adc7a2c73fbd84776d Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 13:31:32 +0000 Subject: [PATCH 6/8] more review comments --- .../Articles/Generating-stubs.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index f49bcf33e..9c1f342db 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -8,20 +8,11 @@ If you've used Protocol Buffers before then generating gRPC Swift stubs should b 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. -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`. - You can use the protoc plugin from the command line directly, or you can make use of a [Swift Package Manager build plugin](https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) convenience which adds the stub generation to the Swift build graph. You may use the build plugin either from the command line or from Xcode. - -> `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. - - - ## Using the build plugin The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. @@ -104,6 +95,8 @@ lower in the file hierarchy supersedes one above it. ### Using 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`. To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with the `--grpc-swift_out=` option: @@ -111,6 +104,9 @@ the `--grpc-swift_out=` option: protoc --grpc-swift_out=. my-service.proto ``` +> `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. + The presence of `--grpc-swift_out` tells `protoc` to use the `protoc-gen-grpc-swift` plugin. By default it'll look for the plugin in your `PATH`. You can also specify the path to the plugin explicitly: From 7c0d31d904890952ca3484016922a95345189764 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 24 Jan 2025 13:32:56 +0000 Subject: [PATCH 7/8] formatting --- .../GRPCCore/Documentation.docc/Articles/Generating-stubs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 9c1f342db..970df6f88 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -8,7 +8,7 @@ If you've used Protocol Buffers before then generating gRPC Swift stubs should b 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. -You can use the protoc plugin from the command line directly, or you can make use of a +You can use the `protoc` plugin from the command line directly, or you can make use of a [Swift Package Manager build plugin](https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) convenience which adds the stub generation to the Swift build graph. You may use the build plugin either from the command line or from Xcode. @@ -50,7 +50,7 @@ are included in the target's source directory and that you have defined at least You must provide a configuration file in the directory which encloses all `.proto` files (in the same directory or a parent). Configuration files, written in JSON, tell the build plugin about the options used for `protoc` invocations. -You must name the file grpc-swift-proto-generator-config.json and structure it in the following format: +You must name the file `grpc-swift-proto-generator-config.json` and structure it in the following format: ```json { "generate": { From 31dfa48e663a33066096de6b4eff4f2ee657a8d6 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 24 Jan 2025 13:42:53 +0000 Subject: [PATCH 8/8] Apply suggestions from code review --- .../Documentation.docc/Articles/Generating-stubs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 970df6f88..88c2108a9 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -17,7 +17,7 @@ You may use the build plugin either from the command line or from Xcode. The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be available -at compile time. This requirements means it is not a good fit for library authors who do not have +at compile time. This requirement means it is not a good fit for library authors who do not have direct control over this. The build plugin detects `.proto` files in the source tree and invokes `protoc` once for each file @@ -43,7 +43,7 @@ targets: [ ) ] ``` -Once this is done you need to ensure that that the `.proto` files to be used for generation +Once this is done you need to ensure that the `.proto` files to be used for generation are included in the target's source directory and that you have defined at least one configuration file. ### Configuration @@ -80,8 +80,8 @@ The options do not need to be specified and each have default values. | `generate.messages` | `true`, `false` | `true` | Generate message stubs | | `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | | `generatedSource.accessLevel` | `"public"`, `"package"`, `"internal"` | `"internal"` | Access level for generated stubs | -| `protoc.executablePath` | N/A | null† | Path to the `protoc` executable | -| `protoc.importPaths` | N/A | null‡ | Import paths passed to `protoc` | +| `protoc.executablePath` | N/A | `null`† | Path to the `protoc` executable | +| `protoc.importPaths` | N/A | `null`‡ | Import paths passed to `protoc` | † The Swift Package Manager build plugin infrastructure will attempt to discover the executable's location if you don't provide one.