Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build & Test

Prerequisites

  • Rust 1.85 or later (edition 2024)
  • Cargo (included with Rust)
  • protobuf compiler (protoc) – required for building laurus-server
  • cargo-zigbuild – optional, only needed to cross-compile static musl binaries locally (see Cross-compiling static musl binaries)

Building

# Build all crates
cargo build

# Build with specific features
cargo build --features embeddings-candle

# Build in release mode
cargo build --release

Cross-compiling static musl binaries

laurus-cli’s release workflow builds fully static x86_64-unknown-linux-musl / aarch64-unknown-linux-musl binaries in addition to the dynamically-linked glibc ones (see Prebuilt binaries).

Prerequisites:

rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl
pip install cargo-zigbuild

Then build with cargo zigbuild in place of cargo build:

cargo zigbuild --release --target x86_64-unknown-linux-musl \
  -p laurus-cli --features embeddings-all

(equivalent to make build-laurus-cli-musl for the x86_64 target).

Why cargo-zigbuild and not apt install musl-tools? Ubuntu’s musl-tools package provides musl-gcc (C) but no musl-g++ (C++). Most of laurus’s --features embeddings-all dependency graph is C-only or pure Rust (aws-lc-sys, onig_sys), but a plain musl-tools setup is one dependency feature flip away from needing C++ again (tokenizers’ esaxx_fast, which laurus deliberately disables – see Feature Flags). cargo-zigbuild uses Zig as the cross C/C++ toolchain, which bundles musl headers and libraries for every target and needs no Docker.

Verify a build is genuinely static:

file target/x86_64-unknown-linux-musl/release/laurus
# -> ELF 64-bit LSB executable, ..., statically linked
readelf -d target/x86_64-unknown-linux-musl/release/laurus | grep NEEDED
# -> (no output)

See build-binary in .github/workflows/release.yml for the CI configuration this mirrors.

Testing

# Run all workspace tests (default features)
cargo test

# Run a specific test by name
cargo test <test_name>

# Run tests for a specific crate
cargo test -p laurus
cargo test -p laurus-cli
cargo test -p laurus-server
cargo test -p laurus-mcp

Language binding tests

Each language binding has its own toolchain (Python virtualenv, Node.js npm, Ruby Bundler, PHP Composer, wasm32-unknown-unknown target). The Makefile wraps these so each target sets up the toolchain before running the suite:

make test-laurus-python   # cargo test -p laurus-python + pytest via Maturin
make test-laurus-nodejs   # npm run build:debug + npm test
make test-laurus-wasm     # cargo build -p laurus-wasm --target wasm32-unknown-unknown
make test-laurus-ruby     # cargo test -p laurus-ruby + Ruby minitest
make test-laurus-php      # cargo build -p laurus-php --release + PHPUnit

laurus-php is excluded from the Cargo workspace because of links = "clang" conflicts with laurus-ruby; it builds and tests as a standalone crate via the Makefile target above. See Makefile for the full target list including the matching format-laurus-* / lint-laurus-* / build-laurus-* variants.

Linting

# Run clippy with warnings as errors
cargo clippy -- -D warnings

Formatting

# Check formatting
cargo fmt --check

# Apply formatting
cargo fmt

Documentation

API Documentation

# Generate and open Rust API docs
cargo doc --no-deps --open

mdBook Documentation

# Build the documentation site
mdbook build docs

# Start a local preview server (http://localhost:3000)
mdbook serve docs

# Lint markdown files
markdownlint-cli2 "docs/src/**/*.md"

# Check binding README / docs / example snippets against the current
# Node.js / WASM / PHP signatures (also run by `make lint` and CI)
python3 scripts/check-binding-snippets.py