Contributing
This chapter covers the development workflow for nano-ros.
Development Setup
Choose the setup tier. base is enough for most code review and
native development; all prepares the full test-all matrix:
just setup # print setup choices
just setup base # workspace tools + zenohd
just setup all # all supported SDKs/services
source ./setup.bash
Build the entire workspace including examples:
just build
Use groups to inspect the command surface:
just --group main --list
just --group full-matrix --list
just --group full-matrix --list zephyr
Quality Checks
Always run just ci after completing a task that needs the full
maintainer gate. This runs the normal checks plus the full test matrix
entry points:
just ci
For a narrower local iteration, run just check and just test.
For platform-specific CI, use just <platform> ci (e.g., just freertos ci).
Testing
nano-ros has several test tiers, each with its own just recipe:
| Recipe | What it tests | External deps |
|---|---|---|
just test-unit | Unit tests (no external deps) | None |
just test-integration | Rust integration tests, no heavy QEMU/Zephyr (builds zenohd automatically) | None |
just test | test-unit + test-integration (default dev tier) | None |
just test-doc | rustdoc doctests for the nros umbrella crate | None |
just test-miri | Undefined behavior detection (standalone) | None |
just qemu test | QEMU bare-metal examples | qemu-system-arm |
just freertos test | FreeRTOS QEMU E2E | qemu-system-arm + arm-none-eabi-gcc |
just nuttx test | NuttX QEMU E2E | nightly + qemu-system-arm |
just threadx_linux test | ThreadX Linux user-space E2E | gcc |
just threadx_riscv64 test | ThreadX RISC-V QEMU E2E | qemu-system-riscv64 |
just zephyr test | Zephyr E2E (native_sim + NSOS) | west |
just esp32 test | ESP32-C3 QEMU E2E | nightly + qemu-system-riscv32 |
just test-all | Everything: test + heavy QEMU/Zephyr/ROS-interop + test-doc + test-miri + C codegen | All of the above |
All test recipes accept a verbose argument for live output.
Test organization
- Reusable Rust tests go in
packages/testing/nros-tests/tests/ - Shell-based test scripts go in
tests/with corresponding justfile entries - Temporary tests can be run directly in the shell, then converted to proper tests once validated
Build isolation
Nextest runs each test file as a separate process in parallel. When multiple tests build the same example with different features, use --target-dir to isolate output directories (e.g., target-safety/, target-zero-copy/). Add new target dirs to the example’s per-directory .gitignore.
Code Style
Rust Edition 2024
nano-ros uses Rust edition 2024, which requires:
unsafe extern "C" { ... }– extern blocks require theunsafekeyword#[unsafe(no_mangle)]–no_manglerequires theunsafeattribute- Unsafe operations inside
unsafe fnneed explicitunsafe { ... }blocks
The nros-c crate keeps #![allow(unsafe_op_in_unsafe_fn)] due to 420+ FFI operations.
Unsafe conventions
- Minimize unsafe usage; prefer safe abstractions
- Document safety invariants with
// SAFETY:comments - Use wrapper types (like
SubscriberBufferRef) to encapsulate unsafe access patterns
no_std patterns
All core crates support #![no_std] with optional std/alloc features:
#[cfg(feature = "alloc")]gatesVec/Boxusage#[cfg(feature = "std")]gates std-only featuresheapless::Vecis used inno_stdcontexts
Unused variables
- Rename to
_namewith a comment explaining why - Use
#[allow(dead_code)]for test struct fields
Message Types
Message types are always generated, never hand-written. Use the codegen tool:
nros generate-rust
Bundled interface definitions live in packages/codegen/interfaces/. Example generated/ directories are gitignored and recreated by just generate-bindings. Only packages/interfaces/rcl-interfaces/generated/ is checked into git.
System Packages
Never install system packages or run sudo directly. If a system dependency is needed, document what the user should install.
Temporary Files
Create temporary files in the project’s tmp/ directory (git-ignored), not in /tmp.
PR Workflow
- Create a branch from
main - Make changes
- Run
just ci– all checks must pass - Submit for review
Verification
For changes to core crates, run the formal verification suite:
just verify # Kani + Verus
just verify-kani # Kani bounded model checking (~3 min)
just verify-verus # Verus deductive proofs (~1 sec)