Proposal: Rust in the Bazel build (rules_rust + hermetic_cc_toolchain)¶
Design record. This proposal is published as written, at its stated status. Later proposals may supersede parts of it, and implementation details drift. It documents the reasoning at a point in time, not the current behaviour of the system — for that, see the docs.
Status: Implemented, then superseded by proposal 010 — the rules_rust + hermetic_cc toolchain shipped (#177) and carried the proposal-007 Rust dynamic module (#178), but was removed when aether_stats moved to a native C++ extension in the custom proxy workspace (proposals 010–012). No Rust remains in the tree. (2026-06-13 design.)
Author: Bruno Palermo
Date: 2026-06-13
Problem Statement¶
Aether is Go + Bazel. Proposal 007 (source↔destination telemetry) needs an Envoy
dynamic module — a native shared library loaded by the stock proxy at runtime.
The performant, no-custom-proxy-build option is a Rust dynamic module (see 007
for the WASM/Rust/C++ analysis). That requires first-class Rust support in the
Bazel build: a Rust toolchain, a way to link a cdylib, and — since the proxy
ships multi-arch (amd64/arm64) — hermetic cross-compilation.
This proposal adds that toolchain layer on its own, decoupled from any module
implementation, so the build-system change can be reviewed and validated in
isolation. The first consumer (the aether_telemetry module) lands in a
follow-up PR stacked on this one.
Goals¶
- Build Rust targets in Bazel (
rules_rust), with a hermetic, pinnedrustc. - Link
cdylibs and cross-compile for linux amd64 + arm64 hermetically, without requiring host clang. - Do not disturb the existing Go/protobuf build — the default C++ toolchain used by cgo/protobuf must stay exactly as-is.
- Keep
bazel test //...green and exercise the Rust toolchain in CI.
Design¶
rules_rust¶
rules_rust 0.70.0. The rust module extension downloads a pinned rustc
(edition 2021, version 1.83.0) — hermetic, independent of any host Rust. No
crate_universe is added here; external-crate management arrives with the first
consumer that needs it (proposal 007).
Superseded (LLVM migration): the C/C++ toolchain described below was later replaced by a hermetic LLVM (
toolchains_llvm, clang 18.1.8 — matching Envoy's hermetic pin — + chromium glibc sysroots), which is now the repo's single registered C/C++ toolchain and additionally supplieslibclangto the SDK bindgen build script (fully hermetic, no host clang/headers). See//bazel/llvmandMODULE.bazel. The Zig (@zig_sdk) sections below are kept for history;--platforms=//bazel/llvm/platform:linux_{amd64,arm64}replaces the@zig_sdk//libc_aware/platform:*invocations.
hermetic_cc_toolchain (the C linker + cross-compile) — superseded¶
hermetic_cc_toolchain 4.1.0 provides a Zig-based C/C++ toolchain
(@zig_sdk). It is the Bazel-native equivalent of the cargo-zigbuild approach
the upstream dynamic-module examples use for multi-arch.
Critically, it is registered libc-aware:
register_toolchains("@zig_sdk//libc_aware/toolchain/...")
libc-aware toolchains only resolve for a platform that declares a libc-version
constraint (@zig_sdk//libc_aware/platform:linux_{amd64,arm64}_gnu.2.28). A
normal bazel build //... / bazel test //... therefore continues to use the
repo's existing default C++ toolchain — the Go/protobuf builds are untouched.
Hermetic cross-compilation is opt-in per invocation, e.g. for the first
consumer (proposal 007):
bazel build //proxy/filters/http/aether_stats:aether_telemetry \
--platforms=@zig_sdk//libc_aware/platform:linux_arm64_gnu.2.28
This is what the module's release-artifact build (proposal 007) uses to produce
both-arch .sos.
This PR adds only the toolchain layer — no Rust target, since the toolchain is exercised by its first consumer (proposal 007, stacked) and the validation below. A standalone smoke target was prototyped and dropped once the real module proved the toolchain.
Validation (2026-06-13)¶
- Module
//proxy/filters/http/aether_stats:aether_telemetry(proposal 007, stacked) builds green on the host toolchain and under--platforms=@zig_sdk//libc_aware/platform:linux_amd64_gnu.2.28and…linux_arm64_gnu.2.28(arm64 output confirmedELF … ARM aarch64), and loads into stockenvoyproxy/envoy:distroless-v1.38.0. - Existing Go/protobuf builds unaffected (default C++ toolchain unchanged; libc-aware Zig toolchains do not resolve for default platforms).
Follow-ups¶
- Proposal 007 stacks on this: vendored Envoy SDK +
crate_universe(serde, serde_json, mockall) + theaether_telemetrymodule + the OCI-artifact / image-volume delivery.