Installation
Embedded Proto consists of two parts. The first is a plugin for protoc, written in Python, which generates the C++ code for your messages. The second is a small C++ library on which the generated code depends. Both come in one package. As of version 4.0.0 this package is on PyPI, and the protobuf compiler comes along with it. You no longer have to install protoc yourself.
The only requirement is Python 3.11 or newer. There are three ways to install Embedded Proto:
- With pip, globally or in a virtual environment.
- With uv, which does the same a lot faster.
- As a git submodule in your project, the way earlier versions were installed.
Which one you choose is up to you. When your project already has a Python virtual environment, install Embedded Proto in there. When you want to track the version of Embedded Proto together with the version of your project in git, use the submodule.
Install with pip
The simplest way is to install the package in a virtual environment of your project:
python -m venv venv
source venv/bin/activate
pip install EmbeddedProtoOn Windows, activate the environment with venv\Scripts\activate instead. When you prefer to have the tools available everywhere, install the package globally:
pip install EmbeddedProtoEither way, you now have two commands available: embeddedproto, which generates the code, and protoc-gen-eams, the plugin itself. Check the installation by asking for the version of the protobuf compiler that came with it:
embeddedproto --versionInstall with uv
uv is a replacement for pip and venv. It resolves and installs packages in a fraction of the time. In a virtual environment of your project:
uv venv
uv pip install EmbeddedProtoRun the commands through uv, so you do not have to activate the environment:
uv run embeddedproto --versionTo have the commands available everywhere, without a virtual environment, install Embedded Proto as a tool:
uv tool install EmbeddedProtoUse Embedded Proto as a submodule
Before version 4.0.0 this was the only way to install Embedded Proto. It is still supported. The advantage is that git tracks which version of Embedded Proto your project uses, and a colleague cloning your project gets the same version. Add the repository as a submodule and commit it:
cd your_project_dir
git submodule add https://github.com/Embedded-AMS/EmbeddedProto.git
git commit -m "Added Embedded Proto as a submodule."Next, enter the Embedded Proto folder and run the install script. The script creates a virtual environment in the folder and installs the package in it:
cd EmbeddedProto
python install.pyThe environment is created with pip by default. When you have uv installed, the same is done a lot faster:
python install.py --installer uvYou can check out the command line parameters of the install script using the help parameter:
python install.py --helpThe commands now live in the virtual environment of the submodule. Run them as EmbeddedProto/venv/bin/embeddedproto on Linux and macOS, or EmbeddedProto\venv\Scripts\embeddedproto on Windows. Two small scripts, protoc-gen-eams and protoc-gen-eams.bat, are included in the root of the submodule. They start the plugin from the virtual environment when you call protoc yourself, as described on the generating source code page.
The C++ source code
The generated code depends on the C++ library of Embedded Proto. When you installed with pip or uv, the source code is inside the package. Ask for its location with:
embeddedproto --cpp-src-locationWhen you use the submodule, the source code is in the src folder of the submodule. The library is header only, so there is nothing to compile on its own. Add two include paths to your toolchain:
- The
srcfolder. - The folder with the generated code.
The headers of the library live in a folder of their own, so that a name like Errors.h cannot collide with a header of your application. Include what you need as <EmbeddedProto/WriteBufferFixedSize.h>, or include the whole library at once with <EmbeddedProto.h>. The generated code includes only what it needs.
Build with C++17. When linking with a C compiler, do not forget to pass -lstdc++ to the linker. This prevents errors like undefined reference to.
A few features of the library are switched on with a compiler define. They are described on their own pages:
| Define | Effect |
|---|---|
MSG_TO_STRING | Enables the to_string function for debugging. |
NULL_TERMINATED_STRINGS | Reserves one extra character in each string field for a null terminator. |
PARTIAL_SERIALIZATION_ENABLED | Enables serializing a message in parts, into a buffer smaller than the message. |
EMBEDDED_PROTO_LITTLE_ENDIAN | Set to 1 or 0 to state the byte order of the target, when the compiler does not. See packed fixed-width fields. |
Your license token
With a commercial license you receive a token. The plugin uses it to put your license header on top of each generated file. Set it once, and it is stored in a configuration file in your home folder:
embeddedproto --set-token YOUR_TOKENThe command directly checks the token with the license server and tells you whether it is active. You can repeat the check at any time with embeddedproto --check-license. When you use the submodule, the install script accepts the same token:
python install.py --token YOUR_TOKENThe configuration file is ~/.config/embeddedproto/config.ini on Linux and macOS, and %APPDATA%\embeddedproto\config.ini on Windows. Do not commit the token to your repository. On a build server, export it as an environment variable instead. The variable always takes precedence over the configuration file:
export EMBEDDEDPROTO_BUILD_TOKEN=YOUR_TOKENFor Embedded Proto developers
Embedded Proto uses CMake to build the unit tests. You need CMake 3.28 or newer and a compiler supporting C++17. The unit tests depend on GTest and GMock, which are included as a git submodule. Clone the repository with the recursive option to get them at the same time:
git clone --recursive https://github.com/Embedded-AMS/EmbeddedProto.git
cd EmbeddedProto
python install.pyNext, build and run the unit tests:
scripts/build_test.sh
scripts/run_tests.shTo run a single test case, call the test executable with a filter:
./build/test/test_EmbeddedProto --gtest_filter="DESIRED_TEST_CASE_NAME"