|
20 | 20 | Before we can write any code we need to create a new Swift Package and configure it
|
21 | 21 | to depend on gRPC Swift.
|
22 | 22 |
|
| 23 | + As a prerequisite you must have the Protocol Buffers compiler (`protoc`) installed. You can |
| 24 | + find the instructions for doing this in the [Protocol Buffers GitHub |
| 25 | + repository](https://github.com/protocolbuffers/protobuf?tab=readme-ov-file#protobuf-compiler-installation). |
| 26 | + The remainder of this tutorial assumes you installed `protoc` and it's available in |
| 27 | + your `$PATH`. |
| 28 | + |
23 | 29 | @Steps {
|
24 | 30 | @Step {
|
25 | 31 | Create a new directory called for the package called `RouteGuide`.
|
|
84 | 90 |
|
85 | 91 | @Code(name: "Package.swift", file: "route-guide-sec01-step08-description.swift")
|
86 | 92 | }
|
| 93 | + |
| 94 | + @Step { |
| 95 | + We'll also add a build plugin. This allows the build system to generate gRPC code at build |
| 96 | + time rather than having to generate it with separate tooling. |
| 97 | + |
| 98 | + @Code(name: "Package.swift", file: "route-guide-sec01-step09-plugin.swift") |
| 99 | + } |
| 100 | + |
| 101 | + @Step { |
| 102 | + A configuration file is required so that the plugin knows what to generate. Create |
| 103 | + a JSON file in the `Sources/Protos` directory called `grpc-swift-proto-generator-config.json` |
| 104 | + with this content. |
| 105 | + |
| 106 | + The name of the file (`grpc-swift-proto-generator-config.json`) is important: the plugin |
| 107 | + looks for files matching this name in the source directory of your target. |
| 108 | + |
| 109 | + @Code(name: "Sources/Protos/grpc-swift-proto-generator-config.json", file: "route-guide-sec01-step10-plugin-config.json") |
| 110 | + } |
87 | 111 | }
|
88 | 112 | }
|
89 | 113 |
|
|
93 | 117 |
|
94 | 118 | @Steps {
|
95 | 119 | @Step {
|
96 |
| - Create a new empty file in the `Protos` directory called `route_guide.proto`. We'll use |
97 |
| - the "proto3" syntax and our service will be part of the "routeguide" package. |
| 120 | + Create a new directory in the `Sources/Protos` directory called `routeguide` |
| 121 | + using `mkdir Sources/Protos/routeguide`. |
| 122 | + } |
| 123 | + |
| 124 | + @Step { |
| 125 | + Create a new empty file in the `Sources/Protos/routeguide` directory |
| 126 | + called `route_guide.proto`. We'll use the "proto3" syntax and our service will be part of |
| 127 | + the "routeguide" package. |
98 | 128 |
|
99 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step01-import.proto") |
| 129 | + It's good practice to organise your `.proto` files according to the package they are |
| 130 | + declared in, that's why we created the `routeguide` directory to match the "routeguide" |
| 131 | + package name. |
| 132 | + |
| 133 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step01-import.proto") |
100 | 134 | }
|
101 | 135 |
|
102 | 136 | @Step {
|
103 | 137 | To define a service we create a named `service` in the `.proto` file.
|
104 | 138 |
|
105 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step02-service.proto") |
| 139 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step02-service.proto") |
106 | 140 | }
|
107 | 141 |
|
108 | 142 | @Step {
|
|
113 | 147 | A *unary RPC* where the client sends a request to the server using the stub
|
114 | 148 | and waits for a response to come back, just like a normal function call.
|
115 | 149 |
|
116 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step03-unary.proto") |
| 150 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step03-unary.proto") |
117 | 151 | }
|
118 | 152 |
|
119 | 153 | @Step {
|
|
123 | 157 | example, you specify a server-side streaming method by placing the `stream`
|
124 | 158 | keyword before the *response* type.
|
125 | 159 |
|
126 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step04-server-streaming.proto") |
| 160 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step04-server-streaming.proto") |
127 | 161 | }
|
128 | 162 |
|
129 | 163 | @Step {
|
|
133 | 167 | and return its response. You specify a client-side streaming method by placing
|
134 | 168 | the `stream` keyword before the *request* type.
|
135 | 169 |
|
136 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step05-client-streaming.proto") |
| 170 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step05-client-streaming.proto") |
137 | 171 | }
|
138 | 172 |
|
139 | 173 | @Step {
|
|
146 | 180 | stream is preserved. You specify this type of method by placing the `stream`
|
147 | 181 | keyword before both the request and the response.
|
148 | 182 |
|
149 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step06-bidi-streaming.proto") |
| 183 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step06-bidi-streaming.proto") |
150 | 184 | }
|
151 | 185 |
|
152 | 186 | @Step {
|
153 | 187 | The `.proto` file also contains the Protocol Buffers message type definitions for all
|
154 | 188 | request and response messages used by the service.
|
155 | 189 |
|
156 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step07-messages.proto") |
| 190 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step07-messages.proto") |
157 | 191 | }
|
158 | 192 | }
|
159 | 193 | }
|
160 | 194 |
|
161 | 195 | @Section(title: "Generating client and server code") {
|
162 | 196 | Next we need to generate the gRPC client and server interfaces from our `.proto`
|
163 |
| - service definition. We do this using the Protocol Buffer compiler, `protoc`, with |
164 |
| - two plugins: one with support for Swift (via [Swift Protobuf](https://github.com/apple/swift-protobuf)) |
165 |
| - and the other for gRPC. This section assumes you already have `protoc` installed. |
| 197 | + service definition. As we're using the build plugin we just need to build our project. |
166 | 198 |
|
167 | 199 | To learn more about generating code check out the <doc:Generating-stubs> article.
|
168 | 200 |
|
169 | 201 | @Steps {
|
170 | 202 | @Step {
|
171 |
| - First we need to build the two plugins for `protoc`, `protoc-gen-swift` and |
172 |
| - `protoc-gen-grpc-swift`. |
173 |
| - |
174 |
| - @Code(name: "Console", file: "route-guide-sec03-step01-protoc-plugins.txt") |
175 |
| - } |
176 |
| - |
177 |
| - @Step { |
178 |
| - We'll generate the code into a separate directory within `Sources` called `Generated` which |
179 |
| - we need to create first. |
180 |
| - |
181 |
| - @Code(name: "Console", file: "route-guide-sec03-step02-mkdir.txt") |
182 |
| - } |
183 |
| - |
184 |
| - @Step { |
185 |
| - Now run `protoc` to generate the messages. This will create |
186 |
| - `Sources/Generated/route_guide.pb.swift`. |
187 |
| - |
188 |
| - @Code(name: "Console", file: "route-guide-sec03-step03-gen-messages.txt") |
189 |
| - } |
190 |
| - |
191 |
| - @Step { |
192 |
| - Run `protoc` again to generate the service code. This will create |
193 |
| - `Sources/Generated/route_guide.grpc.swift`. |
| 203 | + Build the project using `PROTOC_PATH=$(which protoc) swift build`. |
194 | 204 |
|
195 |
| - @Code(name: "Console", file: "route-guide-sec03-step04-gen-grpc.txt") |
| 205 | + If you are using Xcode or another IDE then you'll need to set the environment variable |
| 206 | + appropriately. |
196 | 207 | }
|
197 | 208 | }
|
198 | 209 | }
|
|
0 commit comments