|
| 1 | +# ``protoc_gen_swift`` |
| 2 | + |
| 3 | +@Metadata { |
| 4 | + @DisplayName("protoc-gen-swift") |
| 5 | +} |
| 6 | + |
| 7 | +Code generation helper for use with Google's `protoc` command. |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +The `protoc-gen-swift` program is a _plugin_ to Google's protoc |
| 12 | +compiler that works with protoc to translate proto files into |
| 13 | +Swift code. |
| 14 | + |
| 15 | +## Getting Started |
| 16 | + |
| 17 | +If you've worked with Protocol Buffers in other programming |
| 18 | +languages before, adding Swift support is |
| 19 | +very simple: you just need to build the `protoc-gen-swift` program and |
| 20 | +copy it into any directory in your PATH. The protoc program will find |
| 21 | +and use it automatically, allowing you to build Swift sources for your |
| 22 | +proto files. You will also, of course, need to add the corresponding |
| 23 | +Swift runtime library to your project. |
| 24 | + |
| 25 | +### System Requirements |
| 26 | + |
| 27 | +To use Swift with Protocol buffers, you'll need: |
| 28 | + |
| 29 | +* A recent Swift compiler that includes the Swift Package Manager. |
| 30 | + We recommend using the latest release build from |
| 31 | + [Swift.org](https://swift.org) or the command-line tools included |
| 32 | + with the latest version of Xcode. |
| 33 | + |
| 34 | +* Google's protoc compiler. You can get recent versions from |
| 35 | + [Google's github repository](https://github.com/protocolbuffers/protobuf). |
| 36 | + |
| 37 | +### Build and Install |
| 38 | + |
| 39 | +Building the plugin should be simple on any supported Swift platform: |
| 40 | + |
| 41 | +```sh |
| 42 | +$ git clone https://github.com/apple/swift-protobuf |
| 43 | +$ cd swift-protobuf |
| 44 | +$ swift build -c release |
| 45 | +``` |
| 46 | + |
| 47 | +This will create a binary called `protoc-gen-swift` in the |
| 48 | +`.build/release` directory. To install, just copy this one executable |
| 49 | +anywhere in your PATH. |
| 50 | + |
| 51 | +### Converting .proto files into Swift |
| 52 | + |
| 53 | +To generate Swift output for your .proto files, you run the `protoc` |
| 54 | +command as usual, using the `--swift_out=<directory>` option: |
| 55 | + |
| 56 | +```sh |
| 57 | +$ protoc --swift_out=. my.proto |
| 58 | +``` |
| 59 | + |
| 60 | +The `protoc` program will automatically look for `protoc-gen-swift` in your |
| 61 | +`PATH` and use it. |
| 62 | + |
| 63 | +Each `.proto` input file will get translated to a corresponding `.pb.swift` file |
| 64 | +in the output directory. |
| 65 | + |
| 66 | +#### How to Specify Code-Generation Options |
| 67 | + |
| 68 | +The plugin tries to use reasonable default behaviors for the code it |
| 69 | +generates, but there are a few things that can be configured to |
| 70 | +specific needs. |
| 71 | + |
| 72 | +You can use the `--swift_opt` argument to `protoc` to pass options to the |
| 73 | +Swift code generator as follows: |
| 74 | +```sh |
| 75 | +$ protoc --swift_opt=[NAME]=[VALUE] --swift_out:. foo/bar/*.proto mumble/*.proto |
| 76 | +``` |
| 77 | + |
| 78 | +If you need to specify multiple options, you can use more than one |
| 79 | +`--swift_opt` argument: |
| 80 | +``` |
| 81 | +$ protoc \ |
| 82 | + --swift_opt=[NAME1]=[VALUE1] \ |
| 83 | + --swift_opt=[NAME2]=[VALUE2] \ |
| 84 | + --swift_out=. foo/bar/*.proto mumble/*.proto |
| 85 | +``` |
| 86 | + |
| 87 | +_NOTE:_ protoc 3.2.0 does not recognize `--swift_opt` if you rely on |
| 88 | +`protoc-gen-swift` being found on the `PATH`. To work around this, you need to |
| 89 | +explicitly add the argument `--plugin=[PATH-TO-protoc-gen-swift]` to the |
| 90 | +command line, then the `--swift_opt` argument will be understood. If you are |
| 91 | +using protoc 3.2.1 or later, then this workaround is _not_ needed. |
| 92 | + |
| 93 | +##### Generation Option: `FileNaming` - Naming of Generated Sources |
| 94 | + |
| 95 | +By default, the paths to the proto files are maintained on the |
| 96 | +generated files. So if you pass `foo/bar/my.proto`, you will get |
| 97 | +`foo/bar/my.pb.swift` in the output directory. The Swift plugin |
| 98 | +supports an option to control the generated file names, the option is |
| 99 | +given as part of the `--swift_opt` argument like this: |
| 100 | + |
| 101 | +``` |
| 102 | +$ protoc --swift_opt=FileNaming=[value] --swift_out=. foo/bar/*.proto mumble/*.proto |
| 103 | +``` |
| 104 | + |
| 105 | +The possible values for `FileNaming` are: |
| 106 | + |
| 107 | +* `FullPath` (default): Like all other languages, "foo/bar/baz.proto" makes |
| 108 | + "foo/bar/baz.pb.swift. |
| 109 | +* `PathToUnderscores`: To help with things like the Swift Package |
| 110 | + Manager where someone might want all the files in one directory; |
| 111 | + "foo/bar/baz.proto" makes "foo_bar_baz.pb.swift". |
| 112 | +* `DropPath`: Drop the path from the input and just write all files |
| 113 | + into the output directory; "foo/bar/baz.proto" makes "baz.pb.swift". |
| 114 | + |
| 115 | +##### Generation Option: `Visibility` - Visibility of Generated Types |
| 116 | + |
| 117 | +By default, SwiftProtobuf does not specify a visibility for the |
| 118 | +generated types, methods, and properties. As a result, these will end |
| 119 | +up with the default (`internal`) access. You can change this with the |
| 120 | +`Visibility` option: |
| 121 | + |
| 122 | +``` |
| 123 | +$ protoc --swift_opt=Visibility=[value] --swift_out=. foo/bar/*.proto mumble/*.proto |
| 124 | +``` |
| 125 | + |
| 126 | +The possible values for `Visibility` are: |
| 127 | + |
| 128 | +* `Internal` (default): No visibility is set for the types, so they get the |
| 129 | + default internal visibility. |
| 130 | +* `Public`: The visibility on the types is set to `public` so the types will |
| 131 | + be exposed outside the module they are compiled into. |
| 132 | + |
| 133 | + |
| 134 | +##### Generation Option: `ProtoPathModuleMappings` - Swift Module names for proto paths |
| 135 | + |
| 136 | +By default, the code generator assumes all of the resulting Swift files will |
| 137 | +be put into the same module. However, since protos can reference types from |
| 138 | +another proto file, those generated files might end up in different modules. |
| 139 | +This option allows you to specify that the code generated from the proto |
| 140 | +files will be distributed in multiple modules. This data is used during |
| 141 | +generation to then `import` the module and scope the types. This option |
| 142 | +takes the path of a file providing the mapping: |
| 143 | + |
| 144 | +``` |
| 145 | +$ protoc --swift_opt=ProtoPathModuleMappings=[path.asciipb] --swift_out=. foo/bar/*.proto |
| 146 | +``` |
| 147 | + |
| 148 | +The format of that mapping file is defined in |
| 149 | +[swift_protobuf_module_mappings.proto](../Protos/SwiftProtobufPluginLibrary/swift_protobuf_module_mappings.proto), |
| 150 | +and files would look something like: |
| 151 | + |
| 152 | +``` |
| 153 | +mapping { |
| 154 | + module_name: "MyModule" |
| 155 | + proto_file_path: "foo/bar.proto" |
| 156 | +} |
| 157 | +mapping { |
| 158 | + module_name: "OtherModule" |
| 159 | + proto_file_path: "mumble.proto" |
| 160 | + proto_file_path: "other/file.proto" |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +The `proto_file_path` values here should match the paths used in the proto file |
| 165 | +`import` statements. |
| 166 | + |
| 167 | + |
| 168 | +##### Generation Option: `ImplementationOnlyImports` - `@_implementationOnly`-annotated imports |
| 169 | + |
| 170 | +By default, the code generator does not annotate any imports with `@_implementationOnly`. |
| 171 | +However, in some scenarios, such as when distributing an `XCFramework`, imports |
| 172 | +for types used only internally should be annotated as `@_implementationOnly` to |
| 173 | +avoid exposing internal symbols to clients. |
| 174 | +You can change this with the `ImplementationOnlyImports` option: |
| 175 | + |
| 176 | +``` |
| 177 | +$ protoc --swift_opt=ImplementationOnlyImports=[value] --swift_out=. foo/bar/*.proto mumble/*.proto |
| 178 | +``` |
| 179 | + |
| 180 | +The possible values for `ImplementationOnlyImports` are: |
| 181 | + |
| 182 | +* `false` (default): The `@_implementationOnly` annotation will never be used. |
| 183 | +* `true`: Imports of internal dependencies and any modules defined in the module |
| 184 | +mappings will be annotated as `@_implementationOnly`. |
| 185 | + |
| 186 | +**Important:** Modules cannot be imported as implementation-only if they're |
| 187 | +exposed via public API, so even if `ImplementationOnlyImports` is set to `true`, |
| 188 | +this will only work if the `Visibility` is set to `internal`. |
| 189 | + |
| 190 | + |
| 191 | +### Building your project |
| 192 | + |
| 193 | +After copying the `.pb.swift` files into your project, you will need |
| 194 | +to add the |
| 195 | +[SwiftProtobuf library](https://github.com/apple/swift-protobuf) to |
| 196 | +your project to support the generated code. If you are using the |
| 197 | +Swift Package Manager, you should first check what version of |
| 198 | +`protoc-gen-swift` you are currently using: |
| 199 | + |
| 200 | +``` |
| 201 | +$ protoc-gen-swift --version |
| 202 | +protoc-gen-swift 1.0.1 |
| 203 | +``` |
| 204 | + |
| 205 | +And then add a dependency to your Package.swift file. Adjust the |
| 206 | +`Version()` here to match the `protoc-gen-swift` version you checked |
| 207 | +above: |
| 208 | + |
| 209 | +```swift |
| 210 | +dependencies: [ |
| 211 | + .package(name: "SwiftProtobuf", url: "https://github.com/apple/swift-protobuf.git", from: "1.6.0"), |
| 212 | +] |
| 213 | +``` |
| 214 | + |
| 215 | +If you are using Xcode, then you should: |
| 216 | + |
| 217 | +* Add the Swift source files generated from your protos directly to your |
| 218 | + project. |
| 219 | +* Add this SwiftPM package as dependency of your xcode project: |
| 220 | + [Apple Docs](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) |
| 221 | + |
| 222 | + |
| 223 | + |
| 224 | +## Internals |
| 225 | + |
| 226 | +When you give `protoc` an option of the form `--XYZ-out`, |
| 227 | +it will find and run a program called `protoc-gen-XYZ`. |
| 228 | + |
| 229 | +The `protoc` program then proceeds to read, parse, and validate |
| 230 | +all of your proto files. |
| 231 | +It feeds this information (as a set of "Descriptor" objects) |
| 232 | +to the `protoc-gen-XYZ` program and expects the program to |
| 233 | +produce one or more source code files |
| 234 | +that `protoc` will then save to the correct output location. |
| 235 | + |
| 236 | +The `protoc-gen-swift` program relies heavily |
| 237 | +on the `SwiftProtobuf` library to handle serializing and |
| 238 | +deserializing the protobuf-encoded data used to |
| 239 | +communicate with `protoc`. |
| 240 | +It also relies on another library called `SwiftProtobufPluginLibrary` |
| 241 | +that incorporates a lot of the key knowledge about how |
| 242 | +to produce Swift source code. |
0 commit comments