Skip to content

Commit e413050

Browse files
authored
C++ quick start: fix instructions (#172)
* C++ quick start: fix instructions Closes #95 Closes #97 * Post-review edits * Reworked, and tested, instructions * Updates based on Jan's feedback * Updates following more feedback from Jan
1 parent d30fd6a commit e413050

File tree

1 file changed

+174
-68
lines changed

1 file changed

+174
-68
lines changed

content/docs/quickstart/cpp.md

+174-68
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,168 @@ layout: quickstart
33
title: C++ Quick Start
44
short: C++
55
description: This guide gets you started with gRPC in C++ with a simple working example.
6+
cmake-version: 3.17.0
67
---
78

8-
### Prerequisites
9+
In the C++ world, there's no universally accepted standard for managing project
10+
dependencies. In this quick start, you'll follow steps to build and locally
11+
install gRPC before building and running this quick start's Hello World example.
12+
13+
### Setup
914

10-
#### gRPC
15+
Choose a directory to hold locally installed packages. This page assumes that
16+
the environment variable `MY_INSTALL_DIR` holds this directory path. For
17+
example:
1118

12-
To install gRPC on your system, follow the [instructions to install gRPC C++ via make](https://github.com/grpc/grpc/blob/master/src/cpp/README.md#make).
19+
```sh
20+
$ export MY_INSTALL_DIR=$HOME/local
21+
```
1322

14-
To run the example code, please ensure `pkg-config` is installed on your
15-
machine before you build and install gRPC in the previous step, since the
16-
example `Makefile`s try to look up the installed gRPC path using `pkg-config`.
17-
On Debian-based systems like Ubuntu, this can usually be done via
18-
`sudo apt-get install pkg-config`.
23+
Ensure that the directory exists:
1924

20-
#### Protocol Buffers v3
25+
```sh
26+
$ mkdir -p $MY_INSTALL_DIR
27+
```
2128

22-
While not mandatory to use gRPC, gRPC applications usually leverage Protocol
23-
Buffers v3 for service definitions and data serialization, and our example code
24-
uses Protocol Buffers as well as gRPC. If you don't already have it installed on
25-
your system, you can install the version cloned alongside gRPC. First ensure
26-
that you are running these commands in the gRPC tree you just built in the from
27-
the previous step.
29+
Add the local `bin` folder to your path variable, for example:
2830

2931
```sh
30-
$ cd third_party/protobuf
31-
$ make && sudo make install
32+
$ export PATH="$PATH:$MY_INSTALL_DIR/bin"
3233
```
3334

34-
### Build the example
35+
### Prerequisites
3536

36-
Always assuming you have gRPC properly installed, go into the example's
37-
directory:
37+
#### cmake
38+
39+
Version 3.13 or later of `cmake` is required to install gRPC locally.
40+
41+
- Linux
42+
43+
```sh
44+
$ sudo apt install -y cmake
45+
```
46+
47+
- macOS:
48+
49+
```sh
50+
$ brew install cmake
51+
```
52+
53+
- For general `cmake` installation instructions, see [Installing CMake][].
54+
55+
Check the version of `cmake`:
3856

3957
```sh
40-
$ cd examples/cpp/helloworld/
58+
$ cmake --version
4159
```
4260

43-
Let's build the example client and server:
61+
Under Linux, the version of the system-wide `cmake` can be too low. You can
62+
install a more recent version into your local installation directory as follows:
63+
4464
```sh
45-
$ make
65+
$ wget -q -O cmake-linux.sh https://github.com/Kitware/CMake/releases/download/v{{< param cmake-version >}}/cmake-{{< param cmake-version >}}-Linux-x86_64.sh
66+
$ sh cmake-linux.sh -- --skip-license --prefix=$MY_INSTALL_DIR
67+
$ rm cmake-linux.sh
4668
```
4769

48-
Most failures at this point are a result of a faulty installation (or having
49-
installed gRPC to a non-standard location. Check out [the installation
50-
instructions for details](https://github.com/grpc/grpc/blob/master/src/cpp/README.md#make)).
70+
71+
#### gRPC and Protocol Buffers
72+
73+
While not mandatory, gRPC applications usually leverage [Protocol Buffers][pb]
74+
for service definitions and data serialization, and the example code uses
75+
[proto3][].
76+
77+
The following instructions will locally install gRPC and Protocol Buffers.
78+
79+
1. Install the basic tools required to build gRPC:
80+
81+
- Linux
82+
83+
```sh
84+
$ sudo apt install -y build-essential autoconf libtool pkg-config
85+
```
86+
87+
- macOS:
88+
89+
```sh
90+
$ brew install autoconf automake libtool pkg-config
91+
```
92+
93+
2. Clone the `grpc` repo and its submodules:
94+
95+
```sh
96+
$ git clone --recurse-submodules -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
97+
$ cd grpc
98+
```
99+
100+
3. Build and locally install gRPC and all requisite tools:
101+
102+
```sh
103+
$ mkdir -p cmake/build
104+
$ pushd cmake/build
105+
$ cmake -DgRPC_INSTALL=ON \
106+
-DgRPC_BUILD_TESTS=OFF \
107+
-DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \
108+
../..
109+
$ make -j
110+
$ make install
111+
$ popd
112+
```
113+
114+
More information:
115+
116+
- You can find a complete set of instructions for building gRPC C++ in [Building
117+
from source][from-source].
118+
- For general instructions on how to add gRPC as a dependency to your C++
119+
project, see [Start using gRPC C++][using-grpc].
120+
121+
[from-source]: https://github.com/grpc/grpc/blob/master/BUILDING.md
122+
[using-grpc]: https://github.com/grpc/grpc/tree/master/src/cpp#to-start-using-grpc-c
123+
124+
### Build the example
125+
126+
The example code is part of the `grpc` repo source, which you cloned as part of
127+
the steps of the previous section.
128+
129+
1. Change to the example's directory:
130+
131+
```sh
132+
$ cd examples/cpp/helloworld
133+
```
134+
135+
2. Build the example using `cmake`:
136+
137+
```sh
138+
$ mkdir -p cmake/build
139+
$ pushd cmake/build
140+
$ cmake -DCMAKE_PREFIX_PATH=$MY_INSTALL_DIR ../..
141+
$ make -j
142+
```
143+
144+
{{< note >}}
145+
**Getting build failures?** Most issues, at this point, are a result of a
146+
faulty installation. Ensure that the have the right versions of `cmake`, and
147+
carefully recheck your installation.
148+
{{< /note >}}
149+
51150
52151
### Try it!
53152
54-
From the `examples/cpp/helloworld` directory, run the server, which will listen
55-
on port 50051:
153+
Run the example from the example **build** directory
154+
`examples/cpp/helloworld/cmake/build`:
56155
57-
```sh
58-
$ ./greeter_server
59-
```
156+
1. Run the server:
60157
61-
From a different terminal, run the client:
158+
```sh
159+
$ ./greeter_server
160+
```
62161
63-
```sh
64-
$ ./greeter_client
65-
```
162+
1. From a different terminal, run the client and see the client output:
66163
67-
If things go smoothly, you will see the `Greeter received: Hello world` in the
68-
client side output.
164+
```sh
165+
$ ./greeter_client
166+
Greeter received: Hello world
167+
```
69168
70169
Congratulations! You've just run a client-server application with gRPC.
71170

@@ -74,11 +173,11 @@ Congratulations! You've just run a client-server application with gRPC.
74173
Now let's look at how to update the application with an extra method on the
75174
server for the client to call. Our gRPC service is defined using protocol
76175
buffers; you can find out lots more about how to define a service in a `.proto`
77-
file in [What is gRPC?](/docs/guides/) and [gRPC Basics:
78-
C++](/docs/tutorials/basic/cpp/). For now all you need to know is that both the server and the client
79-
"stub" have a `SayHello` RPC method that takes a `HelloRequest` parameter from
80-
the client and returns a `HelloResponse` from the server, and that this method
81-
is defined like this:
176+
file in [What is gRPC?](/docs/guides) and [gRPC Basics:
177+
C++](/docs/tutorials/basic/cpp). For now all you need to know is that both the
178+
server and the client stub have a `SayHello()` RPC method that takes a
179+
`HelloRequest` parameter from the client and returns a `HelloResponse` from the
180+
server, and that this method is defined like this:
82181
83182
```protobuf
84183
// The greeting service definition.
@@ -98,10 +197,8 @@ message HelloReply {
98197
}
99198
```
100199
101-
Let's update this so that the `Greeter` service has two methods. Edit
102-
`examples/protos/helloworld.proto` (from the root of the cloned repository) and
103-
update it with a new `SayHelloAgain` method, with the same request and response
104-
types:
200+
Edit [examples/protos/helloworld.proto][] and add a new `SayHelloAgain()` method, with the
201+
same request and response types:
105202
106203
```protobuf
107204
// The greeting service definition.
@@ -125,34 +222,36 @@ message HelloReply {
125222
126223
Remember to save the file!
127224
128-
### Generate gRPC code
225+
### Regenerate gRPC code
226+
227+
Before you can use the new service method, you need to recompile the updated
228+
proto file.
129229
130-
Next we need to update the gRPC code used by our application to use the new
131-
service definition. From the `examples/cpp/helloworld` directory:
230+
From the example **build** directory `examples/cpp/helloworld/cmake/build`, run:
132231
133232
```sh
134-
$ make
233+
$ make -j
135234
```
136235
137236
This regenerates `helloworld.pb.{h,cc}` and `helloworld.grpc.pb.{h,cc}`, which
138-
contains our generated client and server classes, as well as classes for
237+
contains the generated client and server classes, as well as classes for
139238
populating, serializing, and retrieving our request and response types.
140239
141240
### Update and run the application
142241
143-
We now have new generated server and client code, but we still need to implement
242+
You have new generated server and client code, but you still need to implement
144243
and call the new method in the human-written parts of our example application.
145244
146245
#### Update the server
147246
148-
In the same directory, open `greeter_server.cc`. Implement the new method like
149-
this:
247+
Open `greeter_server.cc` from the example's root directory. Implement the new
248+
method like this:
150249

151250
```c++
152251
class GreeterServiceImpl final : public Greeter::Service {
153252
Status SayHello(ServerContext* context, const HelloRequest* request,
154253
HelloReply* reply) override {
155-
// ... (pre-existing code)
254+
// ...
156255
}
157256
158257
Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
@@ -167,9 +266,9 @@ class GreeterServiceImpl final : public Greeter::Service {
167266
168267
#### Update the client
169268
170-
A new `SayHelloAgain` method is now available in the stub. We'll follow the same
171-
pattern as for the already present `SayHello` and add a new `SayHelloAgain`
172-
method to `GreeterClient`:
269+
A new `SayHelloAgain()` method is now available in the stub. We'll follow the
270+
same pattern as for the already present `SayHello()` and add a new
271+
`SayHelloAgain()` method to `GreeterClient`:
173272
174273
```c++
175274
class GreeterClient {
@@ -196,10 +295,9 @@ class GreeterClient {
196295
return "RPC failed";
197296
}
198297
}
199-
200298
```
201299
202-
Finally, we exercise this new method in `main`:
300+
Finally, invoke this new method in `main()`:
203301
204302
```c++
205303
int main(int argc, char** argv) {
@@ -212,17 +310,17 @@ int main(int argc, char** argv) {
212310
213311
return 0;
214312
}
215-
216313
```
217314
218315
#### Run!
219316
220-
Just like we did before, from the `examples/cpp/helloworld` directory:
317+
Run the client and server like you did before. Execute the following commands
318+
from the example **build** directory `examples/cpp/helloworld/cmake/build`:
221319
222320
1. Build the client and server after having made changes:
223321
224322
```sh
225-
$ make
323+
$ make -j
226324
```
227325
228326
2. Run the server:
@@ -239,15 +337,23 @@ Just like we did before, from the `examples/cpp/helloworld` directory:
239337
240338
You'll see the following output:
241339
242-
```sh
340+
```nocode
243341
Greeter received: Hello world
244342
Greeter received: Hello again world
245343
```
246344
247345
### What's next
248346
249-
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
250-
and [gRPC Concepts](/docs/guides/concepts/).
251-
- Work through a more detailed tutorial in [gRPC Basics: C++](/docs/tutorials/basic/cpp/).
347+
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides)
348+
and [gRPC Concepts](/docs/guides/concepts).
349+
- Work through a more detailed tutorial in [gRPC Basics: C++](/docs/tutorials/basic/cpp).
252350
- Explore the gRPC C++ core API in its [reference
253-
documentation](/grpc/cpp/).
351+
documentation](/grpc/cpp).
352+
353+
[examples/protos/helloworld.proto]: https://github.com/grpc/grpc/blob/{{< param grpc_release_tag >}}/examples/protos/helloworld.proto
354+
[github.com/google/protobuf/releases]: https://github.com/google/protobuf/releases
355+
[Installing CMake]: https://cmake.org/install
356+
[pb]: https://developers.google.com/protocol-buffers
357+
[proto3]: https://developers.google.com/protocol-buffers/docs/proto3
358+
[repo]: https://github.com/grpc/grpc/tree/{{< param grpc_release_tag >}}
359+
[using-grpc]: https://github.com/grpc/grpc/tree/master/src/cpp#to-start-using-grpc-c

0 commit comments

Comments
 (0)