Getting Started with Protocol Buffers
You should use Google's Protocol Buffers to store the messages sent between servers in the Raft projects: they handle a bunch of serialization and deserialization issues that you would otherwise have to address yourself. Here are a few bits and pieces of information to help you get started with protobufs.
-
I recommend that you use proto3 (the newest version of protobufs) since it provides additional facilities for defining messages, such as
oneof
. -
The root of the documentation for protobufs is at https://developers.google.com/protocol-buffers.
-
To install protobufs as a Git submodule of your project,
cd
to the top-level project directory and then invoke the following shell commands:mkdir install git submodule add https://github.com/protocolbuffers/protobuf.git cd protobuf git submodule update --init --recursive cmake . -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_CXX_STANDARD=17 cmake --build . --parallel 10 cmake --install .
This will create a
protoc
executable in the directoryinstall/bin
, which you can use to compile your.proto
files as described below. I'd recommend adding theinstall/bin
directory to yourPATH
environment variable. The commands above will also create numerous library files in the directoryinstall/lib
, which you will need to link your applications against (see below). -
The first step is to learn about the special-purpose language for defining message formats (
.proto
files). For an introduction to this, see the Language Guide for proto3. -
Once you've written your
.proto
files, you'll need to useprotoc
to compile them into C++ header and class files. To do that, invoke the following shell command:protoc -I $SRC_DIR --cpp_out $DST_DIR foo.proto
In this command,
foo.proto
is the name of the file to compile,$SRC_DIR
is the name of the directory containingfoo.proto
(often.
), and $DST_DIR is the name of the directory whereprotoc
should place the.pb.h
and.pb.cc
files (often.
as well). You should set up yourMakefile
to rerunprotoc
whenever a.proto
file changes. -
Next, you'll need to learn about instantiating protobuf objects and the methods available for reading and writing fields in them. This is also described in C++ Protocol Buffer Basics.
-
You'll also need to learn how to serialize protobufs (e.g., into strings) for transmitting over the network, and how to deserialize back from network data to protobuf objects. This is done with methods such as
SerializeToString
andParseFromString
. There are also many other options available, depending on how you want to structure your code. The best way to learn about these methods is with the C++ API documentation. In particular, the serialization and deserialization methods are all part of theMessageLite
class, which is a superclass of all the protobuf classes. -
Finally, you'll need to compile your application files along with the
.pb.cc
files generated byprotoc
and many library files from theinstall/include/lib
directory. Compile the.pb.cc
files just like your application files, except you'll also need to specify-I install/include
on the command line so that the compiler can find protobuf header files (you may also need this option when compiling your application files that use protocol buffers). To link with the appropriate library packages, add the following lines to your
Makefile
:LIBS := $(shell export PKG_CONFIG_PATH=install/lib/pkgconfig; \ pkg-config --libs protobuf)
Then in the Makefile lines that compile final executables, add
$(LIBS)
.
Installation on MacOS
The instructions above work for Linux, but installing Protocol Buffers under MacOS may require additional work. Here is one set of instructions that seems to work (it ensures that protobufs link against a local installation of Abseil):
- Before the command sequence above, invoke
brew install abseil brew info abseil
- Save information about Abseil's installation path.
- In the command sequence above, replace the first
cmake
command with this:export ABSEIL_PATH=<path from brew info abseil above> cmake . -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_CXX_STANDARD=17 -Dprotobuf_ABSL_PROVIDER=package -DCMAKE_PREFIX_PATH=$(ABSEIL_PATH)
Alternate instructions for installing on MacOS are available in this gist: https://gist.github.com/madelinegannon/393fe7b1a24664abd0976467162f5f14
You may also need to delete existing installations of protobufs:
brew uninstall protobuf
After installation, if you invoke
protoc --version
it should return
something like libprotoc 3.x.x
. If it returns a version number like
libprotoc 25.x.x
, you might have an extra protobuf installation hidden
in your system that is conflicting with the one you want.