C++
The C++ side of the boundary: an application that already owns its screen
stack, hosting xpui screens over a C ABI. This is the repository to read if
you have a firmware written in C++ and want one screen of it in Rust. Not a
rewrite — a screen at a time, called through six lifecycle entry points and an
opaque void*.
Every document in this repository is listed in docs/README.md.
Which crate you want
Section titled “Which crate you want”cpp_host | The worked example, and the only thing any gate in this organisation builds, links and runs the FreeInkUI shim through. Design an ABI change here |
firmware | The same C++ through PlatformIO, for a real ESP32. No gate invokes it, so a break surfaces when somebody builds a firmware |
abi | Two of the five ABI boundaries, checked — the two that cross into the application: xpui_host.h against the Rust that calls it, and xpui_app.h against src/lib.rs and the macro that defines its factory. The other three are the backend's and are checked there |
Using it
Section titled “Using it”Nothing depends on this repository; it is the far end. Using it is following the tutorial with a firmware of your own, or building the worked example:
cmake -S cpp_host -B target/cpp_host -G Ninja -DCMAKE_BUILD_TYPE=Releasecmake --build target/cpp_host./target/cpp_host/xpui-host --headless --frames 30 --selftestWhat it builds on is xpui
and the FreeInkUI backend from
xpui-backends, whose
fui/cpp/ this compiles and links. That one is a sibling checkout, not a
package path: nothing is published, and a git dependency lands in a cargo
checkout directory with no path a CMakeLists.txt can name.
Requirements
Section titled “Requirements”xpui-backends, cloned beside this repository — or named byXPUI_BACKENDS_DIR. Without it the two stages that compile C++ printskipped:and pass on a laptop, fail on CI, andallfails.- The FreeInk SDK's FreeInkUI headers, for those same two stages: named
by
FREEINK_SDK_INCLUDE, or in one of the sibling layoutsfreeink_includeinxtask/src/cpp.rslists. Without them both skip and pass, except on CI, where a skip is a failure.allneeds no local copy: CMake fetches the revisioncpp_host/freeink-sdk.revpins, which CI reads too. - SDL2, for the desktop host's window.
- clang-format 21 or newer, for the C++ format stage; an older binary ignores options it does not know and formats differently, silently.
- CMake and Ninja, for
all.
Checking it
Section titled “Checking it”./build-and-test.sh # format, lint, test, and every snippet./build-and-test.sh all # plus cmake, the link, and nine ctest casesThe checks themselves are in xtask/ — this repository's own list,
in Rust, holding nothing it does not run. ./build-and-test.sh fix formats
in place first. all is the only place in the organisation where the C ABI
is compiled, linked and executed rather than syntax-checked. How a change is
reviewed is in docs/contributing.md.
Where it sits
Section titled “Where it sits”Every arrow is a dependency in a Cargo.toml, and they all point inward
toward xpui, which depends on nothing at all. That is the rule the
organisation is arranged around: a backend can be written without the framework
knowing it exists, and a firmware reaches whatever it needs directly rather
than through whoever happens to sit above it.