Building#
Repository layout#
crates/ Rust engine and capability crates (each crate's README is its landing page)
bindings/ per-language bindings: node, python, dotnet
examples/ runnable end-to-end scenarios and the cross-language conformance generator
conformance/ the vectors every binding asserts, so the languages cannot disagree
docs/ this site: the guides, the capability map, and the pages about the project
sitl/ ArduPilot and PX4 SITL images for the MAVLink interop job
web/ the stylesheets, scripts, typefaces, and front-page data the site is rendered from
assets/ brand and logoDevice and transport simulators live in pamoja-sim and pamoja-loopback, so
the examples and tests run with no hardware.
From source#
cargo build --workspace # build the engine and capability crates
cargo test --workspace # run tests, including doctests and the MQTT round-trip
cd bindings/node
npm install && npm run build # build the native addon and the TypeScript facade
npm test # smoke and conformance tests
cd ../python
python -m venv .venv && . .venv/bin/activate
pip install maturin pytest
maturin develop -m packages/native/Cargo.toml # build the engine, pamoja-native
pip install $(find packages -mindepth 1 -maxdepth 1 -type d ! -name native) # every pure distribution
pytest # smoke and conformance tests
cd ../..
cargo build -p pamoja-ffi --release # build the native C ABI and refresh pamoja.h
dotnet build bindings/dotnet/Pamoja.sln -c Release # build the .NET interop and facade
dotnet run --project bindings/dotnet/tests/Pamoja.Smoke -c Release # smoke and conformance testsjust lists the recipes CI runs, and cargo xtask lists the workspace tasks.
Generated files#
Several committed files are generated and checked in CI, so edit the source they come from and regenerate:
| File | Source | Regenerate with |
|---|---|---|
crates/*/README.md | each crate's lib.rs rustdoc | cargo xtask docs |
docs/SUMMARY.md and the tables in the READMEs and this site | docs/capabilities.toml | cargo xtask docs |
crates/pamoja-ffi/include/pamoja.h | the pamoja-ffi source | cargo build -p pamoja-ffi |
bindings/node/packages/native/index.js and index.d.ts | the Node binding source | npm run build in bindings/node |
bindings/node/packages/*/package.json, tsconfig.json, and README.md | docs/capabilities.toml and each package's imports | cargo xtask docs |
bindings/python/packages/native/python/pamoja/_native/__init__.pyi | the Python binding source | cargo run --bin stub_gen in bindings/python/packages/native |
bindings/python/packages/*/pyproject.toml, README.md, and py.typed | docs/capabilities.toml and each portion's imports | cargo xtask docs |
conformance/vectors.json | the Rust implementation | cargo run -p pamoja-examples --example conformance_vectors |
Guide examples#
Every code block in a guide is spliced from a test that ran in CI. A guide page holds a region such as
<!-- snippet: bindings/python/guides/modbus.py#example -->
<!-- end -->and cargo xtask docs fills it with the lines between # ANCHOR: example and
# ANCHOR_END: example in that file, dedented, under a link to the file.
cargo xtask docs --check fails if the spliced text no longer matches the
source. One file per guide and language:
| Language | File | Run with |
|---|---|---|
| Rust | examples/tests/guides/<name>.rs, one #[test], declared in main.rs | cargo test -p pamoja-examples --test guides |
| TypeScript | bindings/node/guides/<name>.ts, top-level statements with node:assert/strict | npm run test:guides in bindings/node |
| Python | bindings/python/guides/<name>.py, a script with plain assert | pytest in bindings/python |
| C# | bindings/dotnet/samples/Pamoja.Guides/<Name>Guide.cs, a static Run() called from Program.cs | dotnet run --project bindings/dotnet/samples/Pamoja.Guides |
just guides runs all four. No example needs a broker, a server, or hardware:
where a capability is a network client, the example covers what is decidable
without one, and the loopback transport carries the round trips. The TypeScript
files import the @pamoja/<name>
packages through the workspace links under node_modules, so they see each
package the way a user does; build the facade first. The C# project has a plain
Guides namespace rather than a Pamoja.* one, so its examples name types the
way an application does.
This site#
The pages are rendered from docs/ by cargo xtask site, a static-site generator
in the workspace task runner, and the four references are generated into the same
tree: rustdoc for the crates, typedoc for the Node packages, pdoc for the Python
packages, and DocFX for the .NET packages. The reference page for each language
is the way into its generated tree, whose own root pages redirect to it. Every
code block is highlighted when the site is rendered, every link is checked
(references included, once they are in place), and the docs workflow does all of
it on every pull request; the Pages workflow publishes the same tree under
/docs. Locally, the generators run first so the pages can overwrite their roots:
cargo xtask docs # the generated regions, checked in
mkdir -p target/site/docs/reference
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --exclude xtask --exclude pamoja-examples
cp -r target/doc target/site/docs/reference/rust
cd bindings/node/docs && npm ci && npx typedoc # target/site/docs/reference/node
cd bindings/python && pip install pdoc==16.0 && pdoc pamoja '!pamoja._native' -o ../../target/site/docs/reference/python --docformat restructuredtext
dotnet tool install -g docfx --version 2.78.5 && docfx bindings/dotnet/docs/docfx.json
cargo xtask site # the pages, into target/site
cargo xtask site --verify # every link resolves, the references included
node web/serve.mjs --root target/site # serve it at localhost:8099 with live reloadFormatting and lints#
CI runs cargo fmt --all -- --check and cargo clippy --workspace --all-targets -- -D warnings, and the same two over the Node and Python binding crates,
which sit outside the workspace. Run both before pushing; the just ci recipe
runs everything the main CI job does.