Skip to content

Valhalla Rust bindings

C++-to-Rust bindings for Valhalla Routing Engine, powered by cxx.

The valhalla crate provides drop-in infrastructure (cargo add valhalla and you're ready) for utility projects that need to access Valhalla's road graph data, expose additional Valhalla functionality, or benefit from calling Valhalla's routing engine in-process.

valhalla-debug demonstrates this use case.

Features:

  • Tile access: Read Valhalla tiles and access road graph edges (DirectedEdge, EdgeInfo) and nodes (NodeInfo) - see tiles_tests for examples
  • Live traffic: Read and write live traffic directly on a memory-mapped traffic.tar via a fully typed API. See traffic_debug example for more details.
  • Actor API: Route building and routing operations similar to Valhalla's Python bindings - see actor_tests for examples
  • Typed configuration: valhalla::ConfigBuilder provides a typed Rust API with all of Valhalla's defaults - no Python, no JSON files needed - see config_tests for examples

Not supported yet:

  • Logging: Redirect Valhalla logging to Rust's tracing crate or provide an interface for redirecting it to a custom logger.
  • Reading individual tile files: Support reading info from Valhalla tiles from tile_dir (individual file per tile). Currently only tile_extract (single tiles.tar file) is supported.
  • Historical traffic: All minor functionality for out-of-the-box historical traffic support. Currently minor stuff should be done manually, such as converting GraphId to the tile file name or writing historical speeds (free flow, congested, 5m bins) to the csv files.

Design choices:

  • valhalla::GraphReader is intended to be as simple as possible and hold no mutable inner state, leaving the caching and other optimizations to the caller. This allows for easy reuse of the same GraphReader instance across multiple threads.
  • valhalla::Actor accepts only proto::Options and not proto::Api or Valhalla JSON request to have small strongly-typed API. Still, there is a convenience method to convert JSON into proto::Options called valhalla::Actor::parse_json_request().
  • valhalla::ConfigBuilder is generated at compile time from scripts/valhalla_build_config, so it always matches the bundled Valhalla and needs no Python. Config files generated by valhalla_build_config are still supported, but one from another Valhalla version may not load.

Usage

Run cargo add valhalla or add this to your Cargo.toml:

[dependencies]
valhalla = "0.7"

See examples/README.md for runnable examples.

Dependencies

Since Valhalla heavily relies on system libraries, you need to install the following dependencies to build this project:

sudo apt-get update && sudo apt-get install -y --no-install-recommends clang pkg-config build-essential cmake libboost-dev libprotobuf-dev protobuf-compiler zlib1g-dev

See the Valhalla documentation for other platforms.

Release builds can use cross-language LTO on macOS, and on Linux when linking with LLD. For the latter, use clang and LLD of the same LLVM major version as rustc -vV reports:

export CC=clang-22 CXX=clang++-22 AR=llvm-ar-22 RANLIB=llvm-ranlib-22
export RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang-22 -Clink-arg=-fuse-ld=lld-22"

Development

The crate's manifest is the Cargo.toml in the repository root, so run cargo from there. Tests, benchmarks and examples use the Utrecht tileset built by Valhalla's utrecht_tiles CMake target in build/, which needs the data tools dependencies:

cmake -B build -DENABLE_SERVICES=OFF -DENABLE_PYTHON_BINDINGS=OFF
cmake --build build --target utrecht_tiles
cargo test
cargo test --manifest-path src/bindings/rust/examples/Cargo.toml

Valhalla is built with a unity build to speed up compilation, which can complicate debugging and profiling. Disable it with UNITY_BUILD=OFF, e.g. UNITY_BUILD=OFF cargo bench.