bzd-rust
How to write, build, test, format, and contribute Rust code in the bzd monorepo
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
How to write, build, test, format, and contribute Rust code in the bzd monorepo
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
How to write, build, test, and contribute Node.js/JavaScript/Vue code in the bzd monorepo
How to run, test, build, type-check, format, and manage Python dependencies in the bzd monorepo
Core software design principles — ALWAYS load this before planning and before writing any implementation code
How to build, test, run, and maintain Bazel targets in the bzd monorepo — always load this before invoking any ./tools/bazel command
How to read, write, and wire BDL (Bzd Description Language) files and their Bazel rules in the bzd monorepo — load this before touching any .bdl file or bdl_* Bazel rule
How to write, build, test, and contribute C++ code in the bzd monorepo
| name | bzd-rust |
| description | How to write, build, test, format, and contribute Rust code in the bzd monorepo |
| compatibility | opencode |
./tools/bazel — use //rust:defs.bzl custom macros, never raw rules_rust rules directly for binaries/testsbzd_toolchain_rust / rules_rust) — never invoke cargo or rustc directly#![no_std]: Core library code uses #![no_std] for embedded compatibility — avoid std-only APIs in library crates#![no_main]: Library/test crates that use bzd_test must declare #![no_main]bzd_test proc-macro (NOT the standard libtest harness — use_libtest_harness is always false)rust_embassy_test or //rust/targets:embassy) for async tasks on std and bare-metal--config=clippysnake_case for functions and variables (standard Rust convention — the sole exception to the repo-wide camelCase rule)| Path | Purpose |
|---|---|
rust/defs.bzl | Custom Bazel macros: rust_binary, rust_test, rust_embassy_test |
rust/bzd/ | Core #![no_std] library (bzd::println!, bzd::exit!, platform abstractions) |
rust/bzd/base/ | Low-level base types and panic handler |
rust/libs/bzd_test/ | Custom test framework (proc-macro + #![no_std] runtime — works on embedded and std) |
rust/libs/std/ | Standard library group (//rust/libs/std) for linux-only targets needing std |
rust/targets/ | Platform target aliases: //rust/targets:main and //rust/targets:embassy |
rust/targets/std/ | Linux/macOS std target implementations |
rust/targets/esp/ | ESP32 / ESP32S3 target implementations |
rust/grep/ | Reference example: binary + library + inline tests |
rust/embassy/hello/ | Reference example: Embassy async task (cross-platform: linux, ESP32, ESP32S3) |
rust/adventofcode_2025/ | Additional example binaries |
# Build all Rust targets
./tools/bazel build //rust/...
# Test all Rust targets
./tools/bazel test //rust/...
# Test a specific target
./tools/bazel test //rust/grep:lib_test
# Show full test output even on success
./tools/bazel test --test_output=all //rust/grep:lib_test
# Run a binary
./tools/bazel run //rust/grep:grep
# Debug build
./tools/bazel test --config=debug //rust/grep:lib_test
# Update rust-project.json for IDE rust-analyzer support
./tools/bazel run @rules_rust//tools/rust_analyzer:gen_rust_project -- //rust/...
load("//rust:defs.bzl", "rust_binary", "rust_test", "rust_embassy_test")
| Rule | Purpose |
|---|---|
rust_binary | Wraps rules_rust rust_binary with the bzd_runner; use for all runnable binaries |
rust_test | Wraps rust_test; auto-injects //rust/targets:main + //rust/libs/bzd_test; disables libtest harness |
rust_embassy_test | Like rust_test but injects //rust/targets:embassy (Embassy async executor) |
rust_library (for libraries)load("@rules_rust//rust:defs.bzl", "rust_library")
Use rust_library directly for all library targets — no custom wrapper needed.
Key constraints:
use_libtest_harness = True — the custom macros disable it automatically.//rust/targets:main or //rust/libs/bzd_test to deps manually — rust_test injects them.rust_test and rust_embassy_test accept a crate attribute to test an existing rust_library target inline.snake_case for functions and variables (standard Rust convention)PascalCase#![no_std]: required on all core library crates; avoid std-only imports#![no_main]: required on library/test crates using bzd_testprintln! / eprintln!: use bzd::println! (from //rust/bzd) on embedded targetspanic! for errors: return Result types; use ? for propagation#[allow(...)]: only use when Clippy produces a false positive — add a comment explaining why#![no_std]
#![no_main]
pub fn search<'a>(query: &'a str, contents: &'a str) -> impl Iterator<Item = &'a str> {
contents.lines().filter(move |line| line.contains(query))
}
#[cfg(test)]
#[bzd_test::test]
mod tests {
use super::*;
#[test]
fn test_search() -> TestResult {
let result = search("duct", "a duct tape\nanother line");
assert_eq!(result.collect::<Vec<_>>(), vec!["a duct tape"])?;
Ok(())
}
}
rust/<module>/lib.rs:#![no_std]
#![no_main]
pub fn my_function(input: &str) -> bool {
!input.is_empty()
}
#[cfg(test)]
#[bzd_test::test]
mod tests {
use super::*;
#[test]
fn test_my_function() -> TestResult {
assert_eq!(my_function("hello"), true)?;
assert_eq!(my_function(""), false)?;
Ok(())
}
}
rust/<module>/BUILD.bazel:load("@rules_rust//rust:defs.bzl", "rust_library")
load("//rust:defs.bzl", "rust_test")
rust_library(
name = "my_module",
srcs = ["lib.rs"],
visibility = ["//visibility:public"],
deps = [
# Add deps here, e.g. "//rust/libs/std" for std targets
],
)
rust_test(
name = "my_module_test",
crate = ":my_module",
)
deps = ["//rust/my_module:my_module"]
Tests use the custom bzd_test proc-macro framework. This framework works on all platforms (#![no_std] compatible).
#![no_main]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
#[bzd_test::test]
mod tests {
use super::*;
#[test]
fn test_add() -> TestResult {
assert_eq!(add(1, 2), 3)?;
Ok(())
}
#[test]
fn test_add_negative() -> TestResult {
assert_eq!(add(-1, -2), -3)?;
Ok(())
}
#[test]
#[ignore]
fn test_skipped() -> TestResult {
// This test is skipped at runtime
Ok(())
}
}
Key points:
#[bzd_test::test] on the mod tests block (NOT on individual #[test] functions).TestResult (Result<(), TestError>) — automatically in scope inside the #[bzd_test::test] block.assert_eq!(a, b)? — custom macro from bzd_test; must use ? to propagate the assertion failure.#[ignore] skips the test case at runtime (it is registered but not executed).#![no_main] is required at crate root when using bzd_test.// rust/<module>/tests/lib.rs
#![no_std]
#![no_main]
#[cfg(test)]
#[bzd_test::test]
mod tests {
#[test]
fn test_something() -> TestResult {
assert_eq!(1 + 1, 2)?;
Ok(())
}
}
Inline tests (test the library crate directly):
load("@rules_rust//rust:defs.bzl", "rust_library")
load("//rust:defs.bzl", "rust_test")
rust_library(
name = "lib",
srcs = ["lib.rs"],
visibility = ["//visibility:public"],
)
rust_test(
name = "lib_test",
crate = ":lib",
)
Separate test crate:
load("@rules_rust//rust:defs.bzl", "rust_library")
load("//rust:defs.bzl", "rust_test")
rust_library(
name = "tests",
srcs = ["tests/lib.rs"],
)
rust_test(
name = "test_crate",
crate = ":tests",
)
Embassy async test:
load("@rules_rust//rust:defs.bzl", "rust_library")
load("//rust:defs.bzl", "rust_embassy_test")
rust_library(
name = "lib",
srcs = ["lib.rs"],
deps = ["//rust/targets:embassy"],
)
rust_embassy_test(
name = "lib_test",
crate = ":lib",
)
Embassy is the async runtime used for both bare-metal (ESP32) and std (Linux/macOS) targets.
#![cfg_attr(target_os = "none", no_std)]
#![no_main]
// This import brings in the platform bootstrap (panic handler, executor setup).
use embassy as _;
use embassy_executor::Spawner;
#[embassy_executor::task]
async fn my_task() {
// async work here
bzd::exit!(0);
}
#[unsafe(no_mangle)]
pub fn run_embassy(spawner: Spawner) {
spawner.spawn(my_task()).unwrap();
}
Key notes:
use embassy as _ pulls in the platform bootstrap (provides main on std, panic handler on bare-metal).#[unsafe(no_mangle)] pub fn run_embassy(spawner: Spawner) is the mandatory entry point name.bzd::println! and bzd::exit! (from //rust/bzd) work on all platforms.rust_embassy_test (not rust_test) when testing embassy-based crates.#![cfg_attr(target_os = "none", no_std)] keeps the crate #![no_std] on embedded only.| Platform constraint | //rust/targets:main | //rust/targets:embassy | Notes |
|---|---|---|---|
@bzd_platforms//al:linux | ✓ | ✓ | Linux x86_64 |
@bzd_platforms//al:osx | ✓ | ✓ | macOS ARM64 |
@bzd_platforms//al_isa:esp32-xtensa_lx6 | ✓ | ✓ | ESP32 (Xtensa LX6) |
@bzd_platforms//al_isa:esp32s3-xtensa_lx7 | ✓ | ✓ | ESP32-S3 (LX7) |
Platform-constrained test (linux-only):
rust_test(
name = "linux_test",
crate = ":lib",
target_compatible_with = ["@bzd_platforms//al:linux"],
)
Conditional deps by platform:
rust_library(
name = "lib",
srcs = ["lib.rs"],
deps = ["//rust/bzd"] + select({
"@bzd_platforms//al_isa:esp32-xtensa_lx6": ["@bzd_espressif//hal/rust:embassy"],
"@bzd_platforms//al_isa:esp32s3-xtensa_lx7": ["@bzd_espressif//hal/rust:embassy"],
"//conditions:default": ["@crates//:embassy-executor"],
}),
)
Use //rust/libs/std when a library explicitly requires the Rust standard library (linux/osx only):
deps = ["//rust/libs/std"]
# Run the sanitizer (rustfmt + linting) on changed files
./tools/bazel run //:sanitizer
# Run on ALL files in the repo
./tools/bazel run //:sanitizer -- --all
# Check-only mode (report issues, no writes)
./tools/bazel run //:sanitizer -- --check --all
# Run Clippy static analysis on all Rust targets
./tools/bazel build --config=clippy //rust/...
# Run Clippy on a specific target
./tools/bazel build --config=clippy //rust/grep/...
To exclude a directory from sanitizer checks, place a .sanitizerignore file in that directory.
# Full quality gate (tests + sanitizer + static analysis)
./quality_gate.sh
# Test all Rust targets
./tools/bazel test //rust/...
# Sanitizer check only
./tools/bazel run //:sanitizer -- --check --all
# Clippy check only
./tools/bazel build --config=clippy //rust/...
Always run ./tools/bazel run //:sanitizer before committing.