Development Setup¶
This page walks you through setting up a complete local development environment for RockLake. By the end, you will be able to build all crates, run the full test suite, start a local RockLake instance, connect to it with DuckDB, and make changes with confidence that the test suite will catch regressions. The process is straightforward — if you can compile Rust code and have basic command-line skills, you can be contributing within 30 minutes.
Prerequisites¶
Required¶
| Tool | Minimum Version | Purpose | Installation |
|---|---|---|---|
| Rust toolchain | 1.80+ | Build RockLake | rustup.rs |
| Git | 2.30+ | Version control | System package manager |
| C compiler | Any recent | Build native dependencies | Xcode CLI (macOS), gcc (Linux) |
Rust installation:
# Install rustup (manages Rust versions and components)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Ensure you have the latest stable toolchain
rustup update stable
# Verify installation
rustc --version # Should show 1.80.0 or higher
cargo --version # Should show corresponding cargo version
C compiler (needed for some native dependencies like ring, openssl-sys):
Recommended¶
| Tool | Purpose | When Needed |
|---|---|---|
| Docker | Integration tests with MinIO | S3-compatible storage tests |
| DuckDB | End-to-end protocol testing | Verifying DuckLake compatibility |
| Python 3.10+ | Documentation builds | When editing docs |
| MinIO CLI (mc) | Object storage inspection | Debugging storage issues |
| psql | Manual protocol testing | Sending raw SQL to RockLake |
DuckDB installation:
Docker (for MinIO):
Clone and Build¶
# Clone the repository
git clone https://github.com/rocklake/rocklake.git
cd rocklake
# Build all crates in debug mode (faster compile, slower runtime)
cargo build
# Build in release mode (slower compile, faster runtime — for benchmarks)
cargo build --release
The first build downloads and compiles all dependencies. This takes 2–5 minutes depending on your machine. Subsequent builds are incremental and take seconds.
Workspace Structure¶
After cloning, the workspace contains:
rocklake/
├── Cargo.toml # Workspace manifest (lists all member crates)
├── crates/
│ ├── rocklake-core/ # Foundation: types, keys, values, MVCC
│ ├── rocklake-catalog/ # Persistence: read/write operations, GC
│ ├── rocklake-sql/ # SQL classifier (pattern matching)
│ ├── rocklake-pgwire/ # PG wire protocol server (binary lives here)
│ ├── rocklake-ffi/ # C FFI for native DuckDB extension
│ ├── rocklake-datafusion/ # DataFusion catalog provider
├── tests/
│ ├── fixtures/ # Wire corpus and test data
│ └── golden/ # Golden test runner
├── docs/ # Documentation source (MkDocs)
├── benchmarks/ # Benchmark results (JSON)
└── extension/ # DuckDB native extension (C++)
Dependency Graph¶
Crates depend on each other in a strict hierarchy:
graph TD
pgwire[rocklake-pgwire<br/>Binary + protocol] --> sql[rocklake-sql<br/>SQL classifier]
sql --> catalog[rocklake-catalog<br/>Persistence]
catalog --> core[rocklake-core<br/>Types + encoding]
ffi[rocklake-ffi<br/>C FFI] --> catalog
datafusion[rocklake-datafusion<br/>DataFusion] --> catalog You only need to understand the crates relevant to your change. Most contributions touch one or two crates.
Running Tests¶
# Run the complete test suite (all crates)
cargo test
# Run tests for a specific crate
cargo test -p rocklake-core
cargo test -p rocklake-catalog
cargo test -p rocklake-sql
cargo test -p rocklake-pgwire
# Run a specific test by name
cargo test test_schema_key_roundtrip
# Run tests with output visible (for print debugging)
cargo test -- --nocapture
# Run only integration tests
cargo test -p rocklake-catalog --test integration_tests
# Run property-based tests
cargo test -p rocklake-core --test property_tests
The complete test suite should pass on a fresh clone without any additional configuration. Tests use local filesystem storage by default (no S3 access required). If a test requires external services (MinIO, DuckDB), it is gated behind a feature flag or environment variable.
Test Performance¶
| Test Category | Typical Duration | Runs By Default |
|---|---|---|
| Unit tests | 2–5 seconds | Yes |
| Integration tests | 5–15 seconds | Yes |
| Property-based tests | 10–30 seconds | Yes |
| Wire corpus tests | 1–3 seconds | Yes |
| Benchmark suite | 1–5 minutes | No (cargo bench) |
| S3 integration tests | 30–120 seconds | No (requires S3) |
Running RockLake Locally¶
For end-to-end testing, run a local RockLake instance:
# Start RockLake with local filesystem storage
cargo run -- serve --catalog ./dev-catalog --bind 127.0.0.1:5432
# In another terminal, connect with psql
psql -h 127.0.0.1 -p 5432 -U rocklake
# Or connect with DuckDB
duckdb -c "ATTACH 'ducklake:postgresql://localhost:5432/rocklake' AS lake;"
The local filesystem storage is perfect for development — zero latency, no cloud credentials needed, and you can inspect the catalog files directly.
Using MinIO for S3-Compatible Testing¶
For testing with S3-compatible storage (more realistic than local filesystem):
# Start MinIO
docker run -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio server /data --console-address :9001
# Create a bucket
mc alias set local http://localhost:9000 minioadmin minioadmin
mc mb local/rocklake-dev
# Start RockLake pointing to MinIO
AWS_ACCESS_KEY_ID=minioadmin \
AWS_SECRET_ACCESS_KEY=minioadmin \
AWS_ENDPOINT_URL=http://localhost:9000 \
cargo run -- serve --catalog s3://rocklake-dev/catalog/ --bind 127.0.0.1:5432
Editor Setup¶
VS Code¶
Recommended extensions:
- rust-analyzer — Full IDE features (completion, navigation, diagnostics)
- Even Better TOML — Syntax highlighting for Cargo.toml
- CodeLLDB — Debugging support
Settings (.vscode/settings.json):
{
"rust-analyzer.check.command": "clippy",
"rust-analyzer.cargo.features": "all",
"editor.formatOnSave": true,
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}
IntelliJ/CLion¶
Install the Rust plugin. The workspace is automatically detected from Cargo.toml.
Neovim¶
Use rust-analyzer via the native LSP client or nvim-lspconfig. Configuration varies by setup.
Development Workflow¶
The standard workflow for contributing:
1. Create a Feature Branch¶
Branch naming conventions: - fix/ — Bug fixes - feat/ — New features - docs/ — Documentation changes - test/ — Test additions - refactor/ — Code restructuring
2. Make Your Changes¶
Edit files, add tests, update documentation as needed.
3. Validate Locally¶
# Format code (required — CI rejects unformatted code)
cargo fmt
# Lint (required — CI rejects clippy warnings)
cargo clippy --all-targets --all-features
# Run tests (required — CI rejects failing tests)
cargo test
4. Commit¶
Use Conventional Commits format: - feat: — New feature - fix: — Bug fix - docs: — Documentation only - test: — Adding or fixing tests - refactor: — Code change that neither fixes a bug nor adds a feature - perf: — Performance improvement
5. Push and Open PR¶
Open a Pull Request on GitHub. The PR template asks for: - Description of the change - Related issue (if any) - Test coverage explanation - Breaking change notice (if applicable)
Documentation Development¶
RockLake's documentation is built with MkDocs Material:
# Install Python dependencies
pip install -r requirements-docs.txt
# Serve locally with hot reload (auto-refreshes on file changes)
mkdocs serve
# → Open http://127.0.0.1:8000
# Build the static site (for verifying production build)
mkdocs build --strict
The --strict flag makes MkDocs treat warnings as errors (broken links, missing pages). This is what CI uses — fix warnings before pushing.
Troubleshooting¶
Build Fails with Missing System Dependencies¶
# macOS: ensure Xcode CLI tools are installed
xcode-select --install
# Linux: install OpenSSL development headers
sudo apt install libssl-dev # Debian/Ubuntu
sudo dnf install openssl-devel # Fedora/RHEL
Tests Fail on First Run¶
If tests fail immediately after cloning, verify: - Rust version: rustc --version (must be 1.80+) - Clean build: cargo clean && cargo build - No conflicting environment variables (AWS_*, ROCKLAKE_*)
Slow Compilation¶
- Use
cargo build(notcargo build --release) for development - The
sccachetool can speed up repeated builds:cargo install sccache - Incremental compilation is enabled by default in debug mode
Linker Errors on Linux¶
If you see linker errors related to OpenSSL or other system libraries:
# Install all development dependencies at once (Ubuntu/Debian)
sudo apt install build-essential pkg-config libssl-dev cmake
# Verify pkg-config can find OpenSSL
pkg-config --modversion openssl
Port Already in Use¶
If RockLake fails to start with "address already in use":
# Check what is using port 5432
lsof -i :5432
# Use a different port
cargo run -- serve --catalog ./dev-catalog --bind 127.0.0.1:5433
Common Development Tasks¶
Adding a Wire Corpus Entry¶
When you need to capture new SQL patterns from DuckDB:
# Start RockLake with verbose protocol logging
RUST_LOG=rocklake_pgwire=trace cargo run -- serve --catalog ./dev-catalog --bind 127.0.0.1:5433
# In another terminal, run DuckDB with the new operation
duckdb -c "
ATTACH 'ducklake:postgresql://localhost:5433/rocklake' AS lake;
USE lake;
CREATE SCHEMA test_schema;
"
# Copy the SQL from the log output to the corpus file
# tests/fixtures/wire-corpus/duckdb-X.Y.Z/new-operation.sql
Debugging a Specific Test¶
# Run a single test with full output and backtrace
RUST_BACKTRACE=1 cargo test test_name_here -- --nocapture
# Run with debug logging
RUST_LOG=debug cargo test test_name_here -- --nocapture
Profiling Performance¶
# Install flamegraph tool
cargo install flamegraph
# Generate a flamegraph of the benchmark suite
cargo flamegraph --bench catalog_bench -- --bench prefix_scan
# Or profile the running server
cargo build --release
flamegraph -- ./target/release/rocklake serve --catalog ./bench-catalog
Inspecting Storage Contents¶
During development, it can be useful to inspect what RockLake has written to storage:
# For local filesystem storage
ls -la ./dev-catalog/
find ./dev-catalog/ -type f | head -20
# For MinIO
mc ls local/rocklake-dev/ --recursive
Further Reading¶
- Architecture Guide — Understanding the codebase structure
- Testing — Writing and running tests
- Code Style — Formatting and conventions