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::ConfigBuilderprovides 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
tracingcrate 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 onlytile_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
GraphIdto the tile file name or writing historical speeds (free flow, congested, 5m bins) to the csv files.
Design choices:
valhalla::GraphReaderis 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 sameGraphReaderinstance across multiple threads.valhalla::Actoraccepts onlyproto::Optionsand notproto::Apior Valhalla JSON request to have small strongly-typed API. Still, there is a convenience method to convert JSON intoproto::Optionscalledvalhalla::Actor::parse_json_request().valhalla::ConfigBuilderis generated at compile time fromscripts/valhalla_build_config, so it always matches the bundled Valhalla and needs no Python. Config files generated byvalhalla_build_configare 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.