Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions ansible/roles/developer-rust/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# developer-rust

Rust toolchain (rustup + components), cargo tools, and a build environment
tuned to make the edit-build-test loop bearable.
Rust toolchain (rustup + components), cargo tools, LLVM with PGO and BOLT,
and a build environment tuned to make the edit-build-test loop bearable.

## hyperi-rust-setup

Expand Down Expand Up @@ -34,6 +34,36 @@ enables by default; those calls pass through uncached. Setting
`CARGO_INCREMENTAL=1` by hand is different again - sccache then refuses the
build outright. The wins show up on `--release` and on clean rebuilds.

## LLVM, PGO and BOLT

Standard in this role, not an add-on: clang, lld, BOLT and the LLVM development files, for cross-language LTO, bindgen, PGO and post-link optimisation. Re-apply just this part with `--tags rust-llvm`.

`rust_llvm_version` picks the major:

- `latest` (default) -- the newest `llvmorg-N.x.y` release tag upstream.
- `rustc` -- the major the installed rustc was built with (`rustc -vV`).
- an integer, e.g. `22` -- pinned.

Which major matters differs per tool:

- llvm-profdata and llvm-cov must match rustc's LLVM EXACTLY, because the raw profile format changes between majors. rustup's `llvm-tools-preview` supplies matched copies, installed on every rustup host, Macs included.
- Cross-language LTO needs a system LLVM at least as new as rustc's, hence the default.
- BOLT works with any recent major.

Nothing is exported (`LLVM_PROFDATA`, `LLVM_COV`, `LIBCLANG_PATH`): a pinned path goes stale on the next `rustup update`.

**Ubuntu** takes apt.llvm.org's VERSIONED suite (`llvm-toolchain-<codename>-<N>`) and only that. The unversioned suite is the development snapshot, and its unversioned packages replace the archive's clang, llvm and lld box-wide. The key file must hold exactly one key, with the published fingerprint, before anything trusts it. The keyring is `/usr/share/keyrings/llvm.gpg`, the same path hyperi-ci uses. Two Signed-By values for one suite stop apt reading any source list, so a one-line entry for the same suite anywhere else (hyperi-ci's `llvm.list`, upstream's `llvm.sh`) is removed once ours is written. A deb822 file someone else wrote for that suite is used as is, with a warning. A failed run puts the sources back as it found them.

`/usr/local/bin` gets `clang`, `clang++`, `ld.lld`, `llvm-bolt`, `merge-fdata` and `perf2bolt` pointing at `/usr/bin/<tool>-<N>`, so `hyperi-rust-setup` names LLVM N as the cargo linker. A real file, or a link not pointing at some `/usr/bin/<tool>-<major>`, is left alone and reported. Unversioned `bolt` on Ubuntu is the Thunderbolt daemon, so the package is always `bolt-<N>`.

`apt full-upgrade` (and `hyperi-update`) moves patch releases within N. A new major needs a re-converge. `rust_llvm_remove_previous: true` removes the old major's packages when it moves.

**Fedora** installs its own LLVM; there is no third-party repo. Fedora 44 ships 22 and rustc is on 23 (as of 2026-10), so the run warns that cross-language LTO with that rustc fails until Fedora catches up. PGO and coverage still work. A pinned major older than Fedora's takes the compat packages (`llvm21`, `clang21`, ...).

**macOS** installs brew's `llvm` and `lld` (`llvm@N`, plus `lld@N` from 19 up, for a pinned older major). `llvm` is keg-only, so Apple's clang stays the default. `lld` is not: `ld.lld`, `ld64.lld` and `wasm-ld` land on PATH, which is harmless because Apple's linker is `ld`. Homebrew builds no BOLT for macOS.

At the end the run compares the system major with rustc's. Older warns. Newer is fine, but merge Rust profiles with rustup's llvm-profdata, not the system one. A pinned major the host cannot package also warns.

## Keeping the caches bounded

Three caches, three mechanisms, and only one of them is ours. Apply the lot
Expand Down
37 changes: 37 additions & 0 deletions ansible/roles/developer-rust/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,43 @@ rust_verify_wrapper: true
# an existing config, so nothing is destroyed on a host we do not control.
rust_retire_superseded_config: true

# ---------------------------------------------------------------------------
# LLVM, PGO and BOLT
# ---------------------------------------------------------------------------
# clang, lld, BOLT and the LLVM development files, for cross-language LTO,
# bindgen, PGO and post-link optimisation. rustup's llvm-tools component still
# supplies llvm-profdata and llvm-cov, because those must match rustc's own
# LLVM major exactly and the system copy need not.
rust_llvm_enabled: true

# latest | rustc | <major>. `latest` is the newest LLVM release tag upstream,
# `rustc` is the major the installed rustc was built with, and an integer pins
# one. Cross-language LTO needs a system LLVM at least as new as rustc's, which
# is why the default leans new. Fedora installs its distro LLVM and warns when
# that is below the major asked for.
rust_llvm_version: latest

# apt.llvm.org's published signing key. The keyring path is the one hyperi-ci
# uses for the same repository: two different Signed-By values for one suite
# stop apt reading any source list.
rust_llvm_apt_key_fingerprint: 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421 # gitleaks:allow -- public key fingerprint
rust_llvm_apt_keyring: /usr/share/keyrings/llvm.gpg

# Unversioned names in /usr/local/bin pointing at the installed major (Ubuntu
# only; Fedora and macOS already have their own unversioned names). A real file
# or a link we did not make at one of these paths is left alone and reported.
rust_llvm_links:
- clang
- clang++
- ld.lld
- llvm-bolt
- merge-fdata
- perf2bolt

# Remove the previous major's packages when the resolved major moves (Ubuntu
# only). Off, because a project may still pin the older clang by name.
rust_llvm_remove_previous: false

# ---------------------------------------------------------------------------
# Build cache caps
# ---------------------------------------------------------------------------
Expand Down
Loading
Loading