01 — Setup¶
Before any netcode you need two things:
- the
liblattice.soshared library (the core), and - the
lattice/lattice.hheader (the only file you include).
Your program includes the header, links the library, and calls the extern "C" functions. That's
the whole integration surface — no internal headers, no C++ types across the boundary.
Verified against: reference/README.md (include/lattice/lattice.h — "the only file a binding
includes"); reference/include/lattice/lattice.h:5-8.
Requirements¶
- A C++ toolchain:
g++with-std=c++20(tested on g++ 11). The examples use no external dependencies. pthread(the core links-lpthreadfor its worker job pool).
Verified against: examples/README.md ("Toolchain: g++ with -std=c++20 … No external
dependencies"); reference/build.sh:61-62.
You include a C header, but you can compile as C++
lattice.h is pure C wrapped in extern "C", so it is callable from C or C++. Every example
and test in the repo is C++ (.cpp), which is the path this tutorial follows. The header guards
the extern "C" with #ifdef __cplusplus, so a C compiler works too.
Verified against: reference/include/lattice/lattice.h:42-44.
1. Build liblattice.so¶
The reference ships a g++ fallback build (build.sh) that needs no cmake. From
reference/:
cd reference
./build.sh # build only → build/liblattice.so
./build.sh run # build, then run the conformance harness
This produces reference/build/liblattice.so (plus lattice_conformance, lattice_relay, and
lattice_nat_unit). The library is built -fPIC -fvisibility=hidden with -DLATTICE_BUILD=1, so
only the LATTICE_API-marked ABI functions are exported — no C++ symbols leak.
Verified against: reference/build.sh:57-62, :96; the LATTICE_API visibility macro at
reference/include/lattice/lattice.h:38-40.
There is also a CMake path
If you prefer cmake, reference/CMakeLists.txt builds the same targets:
liblattice.so.
Verified against:
reference/README.md ("Build & run"); reference/CMakeLists.txt.
Confirm the exported C symbols¶
The whole ABI is C. You can see exactly what the library exposes:
Every symbol is a flat lattice_* C function — that flat surface is the contract your binding
compiles against.
Verified against: reference/README.md ("Inspect the exported C symbols").
2. Compile + link your program¶
Point the compiler at the header with -I, link the library with -L/-llattice, and add
-lpthread. Use an $ORIGIN rpath so the executable finds liblattice.so sitting beside it,
regardless of the working directory — this is exactly how the reference links its conformance
harness:
g++ -std=c++20 -O2 \
-I/path/to/reference/include \
-o my_server my_server.cpp \
-L/path/to/reference/build -llattice -lpthread \
-Wl,-rpath,'$ORIGIN'
Verified against: reference/build.sh:64-69 (the conformance harness is compiled with exactly
this shape: -I…/include, -L…/build -llattice -lpthread -Wl,-rpath,'$ORIGIN').
Your .cpp includes just the one header:
Verified against: reference/tests/two_process.cpp:28 (#include <lattice/lattice.h> — the file
includes nothing else from Lattice); examples/starter-server-module/server_main.cpp:20.
A ready-made template build script¶
The examples/starter-server-module/build.sh is a copy-paste starting point. It compiles
server_main.cpp against the header and links liblattice.so, using -rpath so the binary finds
the library:
"$CXX" -std=c++20 -Wall -Wextra -O2 \
-I"$SNAP/include" \
-o "$OUT/starter_server" \
"$HERE/server_main.cpp" \
-L"$LIBDIR" -llattice -Wl,-rpath,"$LIBDIR" -lpthread
Verified against: examples/starter-server-module/build.sh:46-50.
The examples build their own copy of liblattice.so
To stay decoupled from the live core tree, the examples build the library from a snapshot
(examples/anti-cheat-demo/native-snapshot/) into examples/anti-cheat-demo/build/, and the
starter module reuses it (building it on demand if missing). To build against your own Lattice
install instead, point the -I (header) and -L/-rpath (library) flags at it. Running
bash build.sh run in either example builds everything and runs it.
Verified against: examples/README.md ("Decoupling", "Notes");
examples/starter-server-module/build.sh:36-40.
3. Verify it works¶
Run the reference conformance harness — it links liblattice.so through the public header only
(exactly like your binding) and round-trips the bit codec, then stands up a SERVER and a CLIENT
runner over the loopback transport and asserts spawn/replicate/RPC/despawn end to end:
It prints [PASS]/[FAIL] per check, a summary, and returns non-zero on any failure.
Verified against: reference/README.md ("What the conformance harness proves");
reference/build.sh:98-101.
You can also build and run the two runnable examples:
cd examples/starter-server-module && bash build.sh run # a minimal server module
cd examples/anti-cheat-demo && bash build.sh run # the opt-in anti-cheat layer
Verified against: examples/README.md ("Build & run" for each example).
The build baked-in version¶
Each build stamps a build-version id into the library as the exported
lattice_module_version() symbol (format <version>_<YYYYMMDD>_<epoch_millis>). It never enters
the wire format, so it can't affect determinism; it exists so an operator can confirm which build is
running. You can print it from any program:
Verified against: reference/include/lattice/lattice.h:407-419;
examples/starter-server-module/server_main.cpp:110; the id is generated + baked in at
reference/build.sh:13-26.
Next: 02 — Your first runner, where you create a lattice_runner, wire up
callbacks, and pump the tick loop.