|
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 [gRPC Swift Protobuf |
| 25 | + documentation](https://swiftpackageindex.com/grpc/grpc-swift-protobuf/documentation/grpcprotobuf/installing-protoc). |
| 26 | + The remainder of this tutorial assumes you installed `protoc` and it's available in |
| 27 | + your `$PATH`. |
| 28 | + |
| 29 | + You may notice that the `swift` commands are all prefixed with `PROTOC_PATH=$(which protoc)`, |
| 30 | + this is to let the build system know where `protoc` is located so that it can generate stubs |
| 31 | + for you. You can read more about it in the [gRPC Swift Protobuf |
| 32 | + documentation](https://swiftpackageindex.com/grpc/grpc-swift-protobuf/documentation/grpcprotobuf/generating-stubs). |
| 33 | + |
23 | 34 | @Steps {
|
24 | 35 | @Step {
|
25 | 36 | Create a new directory called for the package called `RouteGuide`.
|
|
84 | 95 |
|
85 | 96 | @Code(name: "Package.swift", file: "route-guide-sec01-step08-description.swift")
|
86 | 97 | }
|
| 98 | + |
| 99 | + @Step { |
| 100 | + We'll also add a build plugin. This allows the build system to generate gRPC code at build |
| 101 | + time rather than having to generate it with separate tooling. |
| 102 | + |
| 103 | + @Code(name: "Package.swift", file: "route-guide-sec01-step09-plugin.swift") |
| 104 | + } |
| 105 | + |
| 106 | + @Step { |
| 107 | + A configuration file is required so that the plugin knows what to generate. Create |
| 108 | + a JSON file in the `Sources/Protos` directory called `grpc-swift-proto-generator-config.json` |
| 109 | + with this content. |
| 110 | + |
| 111 | + The name of the file (`grpc-swift-proto-generator-config.json`) is important: the plugin |
| 112 | + looks for files matching this name in the source directory of your target. |
| 113 | + |
| 114 | + @Code(name: "Sources/Protos/grpc-swift-proto-generator-config.json", file: "route-guide-sec01-step10-plugin-config.json") |
| 115 | + } |
87 | 116 | }
|
88 | 117 | }
|
89 | 118 |
|
|
93 | 122 |
|
94 | 123 | @Steps {
|
95 | 124 | @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. |
| 125 | + Create a new directory in the `Sources/Protos` directory called `routeguide` |
| 126 | + using `mkdir Sources/Protos/routeguide`. |
| 127 | + } |
| 128 | + |
| 129 | + @Step { |
| 130 | + Create a new empty file in the `Sources/Protos/routeguide` directory |
| 131 | + called `route_guide.proto`. We'll use the "proto3" syntax and our service will be part of |
| 132 | + the "routeguide" package. |
98 | 133 |
|
99 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step01-import.proto") |
| 134 | + It's good practice to organize your `.proto` files according to the package they are |
| 135 | + declared in, that's why we created the `routeguide` directory to match the "routeguide" |
| 136 | + package name. |
| 137 | + |
| 138 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step01-import.proto") |
100 | 139 | }
|
101 | 140 |
|
102 | 141 | @Step {
|
103 | 142 | To define a service we create a named `service` in the `.proto` file.
|
104 | 143 |
|
105 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step02-service.proto") |
| 144 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step02-service.proto") |
106 | 145 | }
|
107 | 146 |
|
108 | 147 | @Step {
|
|
113 | 152 | A *unary RPC* where the client sends a request to the server using the stub
|
114 | 153 | and waits for a response to come back, just like a normal function call.
|
115 | 154 |
|
116 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step03-unary.proto") |
| 155 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step03-unary.proto") |
117 | 156 | }
|
118 | 157 |
|
119 | 158 | @Step {
|
|
123 | 162 | example, you specify a server-side streaming method by placing the `stream`
|
124 | 163 | keyword before the *response* type.
|
125 | 164 |
|
126 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step04-server-streaming.proto") |
| 165 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step04-server-streaming.proto") |
127 | 166 | }
|
128 | 167 |
|
129 | 168 | @Step {
|
|
133 | 172 | and return its response. You specify a client-side streaming method by placing
|
134 | 173 | the `stream` keyword before the *request* type.
|
135 | 174 |
|
136 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step05-client-streaming.proto") |
| 175 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step05-client-streaming.proto") |
137 | 176 | }
|
138 | 177 |
|
139 | 178 | @Step {
|
|
146 | 185 | stream is preserved. You specify this type of method by placing the `stream`
|
147 | 186 | keyword before both the request and the response.
|
148 | 187 |
|
149 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step06-bidi-streaming.proto") |
| 188 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step06-bidi-streaming.proto") |
150 | 189 | }
|
151 | 190 |
|
152 | 191 | @Step {
|
153 | 192 | The `.proto` file also contains the Protocol Buffers message type definitions for all
|
154 | 193 | request and response messages used by the service.
|
155 | 194 |
|
156 |
| - @Code(name: "Protos/route_guide.proto", file: "route-guide-sec02-step07-messages.proto") |
| 195 | + @Code(name: "Sources/Protos/routeguide/route_guide.proto", file: "route-guide-sec02-step07-messages.proto") |
157 | 196 | }
|
158 | 197 | }
|
159 | 198 | }
|
160 | 199 |
|
161 | 200 | @Section(title: "Generating client and server code") {
|
162 | 201 | 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. |
| 202 | + service definition. As we're using the build plugin we just need to build our project. |
166 | 203 |
|
167 | 204 | To learn more about generating code check out the <doc:Generating-stubs> article.
|
168 | 205 |
|
169 | 206 | @Steps {
|
170 | 207 | @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`. |
| 208 | + Build the project using `PROTOC_PATH=$(which protoc) swift build`. |
194 | 209 |
|
195 |
| - @Code(name: "Console", file: "route-guide-sec03-step04-gen-grpc.txt") |
| 210 | + If you are using Xcode or another IDE then you'll need to set the environment variable |
| 211 | + appropriately. |
196 | 212 | }
|
197 | 213 | }
|
198 | 214 | }
|
|
464 | 480 |
|
465 | 481 | @Steps {
|
466 | 482 | @Step {
|
467 |
| - In one terminal run `swift run RouteGuide --server` to start the server. |
| 483 | + In one terminal run `PROTOC_PATH=$(which protoc) swift run RouteGuide --server` to start the server. |
468 | 484 |
|
469 | 485 | @Code(name: "Console", file: "route-guide-sec07-step01-server.txt")
|
470 | 486 | }
|
471 | 487 |
|
472 | 488 | @Step {
|
473 |
| - In another terminal run `swift run RouteGuide` to run the client program. |
| 489 | + In another terminal run `PROTOC_PATH=$(which protoc) swift run RouteGuide` to run the client program. |
474 | 490 |
|
475 | 491 | @Code(name: "Console", file: "route-guide-sec07-step02-client.txt")
|
476 | 492 | }
|
|
0 commit comments