CMake quickstart#
This tutorial shows you how to build and run our CMake quickstart project. The project is a minimal, complete example of a CMake-built firmware application that pulls in Pigweed as a dependency and implements RPC via pw_rpc and pw_system. The firmware app functions as an RPC server that listens on a local TCP socket for RPC requests. You will be able to simulate this firmware on your development host via Host Device Simulator. Using pw_console you will send RPC requests to the simulated firmware. All RPC requests and responses are structured as protobufs. Protobuf codegen happens automatically as part of the CMake build.
Caution
In general Pigweed does not recommend CMake for new projects and won’t be able to provide extensive support for new projects that choose CMake. See Build system integrations for more information.
Limitations#
This example has only been verified to work on Debian.
The example is only set up to build a host-side simulation of the firmware. It does not set up a cross-compilation toolchain or provide flashing tools.
The firmware build intentionally avoids a bootstrap to demonstrate manual setup of Pigweed modules in a CMake project. Most of the toolchain must be installed globally and available on the system path. The project uses a bootstrap to simplify the client-side manual testing but this is only to minimize the project’s complexity. It’s possible to implement the demonstrated client without a bootstrap.
Install dependencies#
sudo apt-get install -y build-essential cmake \
ninja-build protobuf-compiler python3 \
python3-protobuf python3-serial
Set up the repo#
Clone the repo.
git clone https://pigweed.googlesource.com/pigweed/quickstart/cmake quickstartcdinto the root dir of the repo.cd quickstart
Source code summary#
The project only has a handful of source code files. Here’s an explanation of each one.
//CMakeLists.txt: Fetches dependencies, configures Pigweed backends, sets up C++ and Python protobuf codegen, and defines therpc_demoexecutable target.//main.cc: Initializespw_systemand implementsUserAppInitto register the customMathService.//math_service.proto: Defines the protobuf serviceMathServicewith anAddmethod.//math_service.h: Implements theMathServicedefined inmath_service.proto.//run_console.py: Sets up the Python path to include generated protos and launches an RPC client.
Build the project#
Configure the CMake build:
cmake -B build -S . -G NinjaAside from getting ready to build the firmware, a few other non-obvious important things happen during this step:
The Pigweed and Nanopb repos are fetched as dependencies. See the FetchContent invocations in
CMakeLists.txt.Pigweed backend variables are configured.
Python and C++ protobuf codegen is configured.
See the comments in
CMakeLists.txtfor more context.Run the CMake build:
cmake --build build --target rpc_demo
Generated files summary#
The following files are generated during the CMake build.
//build/rpc_demo: The firmware binary.//build/math_service/nanopb/math_service.pb.*: Nanopb-generated C code for themath_service.protomessages.//build/math_service/nanopb_rpc/math_service.rpc.pb.h: Pigweed RPC generated C++ header for themath_service.protoservice.//build/generated_python/python/math_service_pb2.py: Python protobuf module generated frommath_service.proto, used byrun_console.py.//build/python_packages/: Python protobuf modules generated from Pigweed internal protos, required by Pigweed RPC plugins.
Run the demo#
Open a console tab and run
./build/rpc_demo. The simulated firmware device boots up and starts listening onlocalhost:33000.Open another console tab and
cdinto the root of the upstream Pigweed repo.cd third_party/pigweedBootstrap an environment for
pw_console.. bootstrap.shNote
As mentioned in Limitations, bootstrap is only used here to simplify and speed up the manual testing part of the demo. It’s possible to use
pw_consolewithout a bootstrap.Start a
pw_consolesession.python3 ../../../run_console.py --socket-addr localhost:33000In the Python REPL of
pw_consoleinvoke theEchoRPC.>>> device.rpcs.pw.rpc.EchoService.Echo(msg="hello") (Status.OK, pw.rpc.EchoMessage(msg="hello"))
You should see the server respond with a tuple containing
Status.OKfollowed by a response containing the same message that you sent.Now try invoking the
AddRPC. You should see the server respond with a tuple containingStatus.OKagain followed by the correct sum.>>> device.rpcs.rpc.math.MathService.Add(a=5, b=3) (Status.OK, rpc.math.AddResponse(result=8))
Go back to the tab running the simulated firmware device. You should see the server logging messages.
Awaiting connection on port 33000 Client connected INF pw_system initialized, main thread sleeping... INF System init INF Registering RPC services INF Starting threads INF Running RPC server INF Registering custom MathService INF Server received Add: 5 + 3 INF Simulated device is still alive
Next steps#
Talk to us in the
#cmake-buildchannel of our Discord.Learn more about Pigweed’s CMake support.