From 3b8a43a572a636045baa05347b5a54fa653e73ba Mon Sep 17 00:00:00 2001 From: leynos Date: Wed, 29 Jul 2026 00:38:55 +0200 Subject: [PATCH 01/24] Add opt-in mold and Cranelift local build acceleration Introduce pinned toolchain contracts and Make targets for accelerated local debug builds, without changing any existing quality gate or CI path. - Pin the mold release and its artefact checksums under `tools/mold/`, and the Cranelift-bearing nightly under `tools/cranelift/`, so the linker, backend, and toolchain move in lockstep. - Add `tools/dev-fast/config.toml`, a Cargo fragment that is deliberately *not* `.cargo/config.toml`. Cargo auto-discovers that path, which would leak nightly-only unstable flags and a Linux-only linker choice into CI's stable and MSRV legs, release packaging, coverage, and the formal-verification toolchains. It is reachable only through `cargo --config` from the new `dev-*` targets. - Add `make install-dev-fast`, `make dev-fast-check`, `make dev-build`, `make dev-test`, and `make bench-build`, backed by shell helpers under `scripts/`. The capability check gates the build targets so a missing tool yields an actionable installation hint rather than an opaque codegen-backend or linker failure. - Gate the mold link argument behind `cfg(target_os = "linux")` so macOS and Windows fall back to the platform linker. --- Makefile | 30 +++++++++++++- scripts/bench-build.sh | 81 +++++++++++++++++++++++++++++++++++++ scripts/dev-fast-check.sh | 62 ++++++++++++++++++++++++++++ scripts/dev-fast-common.sh | 63 +++++++++++++++++++++++++++++ scripts/install-dev-fast.sh | 74 +++++++++++++++++++++++++++++++++ tools/cranelift/VERSION | 1 + tools/dev-fast/config.toml | 29 +++++++++++++ tools/mold/SHA256SUMS | 2 + tools/mold/VERSION | 1 + 9 files changed, 342 insertions(+), 1 deletion(-) create mode 100755 scripts/bench-build.sh create mode 100755 scripts/dev-fast-check.sh create mode 100644 scripts/dev-fast-common.sh create mode 100755 scripts/install-dev-fast.sh create mode 100644 tools/cranelift/VERSION create mode 100644 tools/dev-fast/config.toml create mode 100644 tools/mold/SHA256SUMS create mode 100644 tools/mold/VERSION diff --git a/Makefile b/Makefile index f3f0ed895..e9542a616 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help all clean test test-nextest doctest test-workflow-contracts test-typos-config build release lint lint-clippy lint-whitaker fmt check-fmt typecheck markdownlint spelling spelling-config spelling-helper-test nixie install-kani kani-check kani-full kani-ir install-verus verus formal-pr +.PHONY: help all clean test test-nextest doctest test-workflow-contracts test-typos-config build release lint lint-clippy lint-whitaker fmt check-fmt typecheck markdownlint spelling spelling-config spelling-helper-test nixie install-kani kani-check kani-full kani-ir install-verus verus formal-pr install-dev-fast dev-fast-check dev-build dev-test bench-build APP ?= netsuke CARGO ?= $(shell command -v cargo 2>/dev/null || printf '%s' "$$HOME/.cargo/bin/cargo") @@ -18,6 +18,19 @@ KANI_FLAGS ?= KANI_INSTALL_FLAGS ?= KANI_CHECK_FLAGS ?= KANI_VERSION_FILE ?= tools/kani/VERSION +# Opt-in local build acceleration. The Cargo fragment is deliberately not +# `.cargo/config.toml`, so only the `dev-*` targets below can reach it and CI's +# stable, MSRV, release, coverage, and formal-verification legs stay on the +# supported LLVM backend and platform linker. +MOLD_VERSION_FILE ?= tools/mold/VERSION +MOLD_SHA256SUMS_FILE ?= tools/mold/SHA256SUMS +CRANELIFT_TOOLCHAIN_FILE ?= tools/cranelift/VERSION +DEV_FAST_CONFIG ?= tools/dev-fast/config.toml +DEV_FAST_ENV = MOLD_VERSION_FILE='$(MOLD_VERSION_FILE)' \ + MOLD_SHA256SUMS_FILE='$(MOLD_SHA256SUMS_FILE)' \ + CRANELIFT_TOOLCHAIN_FILE='$(CRANELIFT_TOOLCHAIN_FILE)' \ + DEV_FAST_CONFIG='$(DEV_FAST_CONFIG)' +DEV_FAST_TOOLCHAIN = $$(tr -d '[:space:]' <'$(CRANELIFT_TOOLCHAIN_FILE)') MDLINT ?= $(shell command -v markdownlint-cli2 2>/dev/null || printf '%s' "$$HOME/.bun/bin/markdownlint-cli2") NIXIE ?= nixie # Single source of truth for the typos version; the markdownlint target and CI @@ -148,6 +161,21 @@ verus: ## Run the Verus proof entry point formal-pr: ## Run pull-request formal-verification checks $(MAKE) kani-check +install-dev-fast: ## Install the pinned mold linker and Cranelift backend + @$(DEV_FAST_ENV) scripts/install-dev-fast.sh + +dev-fast-check: ## Check the mold and Cranelift local build prerequisites + @$(DEV_FAST_ENV) scripts/dev-fast-check.sh + +dev-build: dev-fast-check ## Build the debug binary with Cranelift and mold + RUSTUP_TOOLCHAIN=$(DEV_FAST_TOOLCHAIN) $(CARGO) --config '$(DEV_FAST_CONFIG)' build $(BUILD_JOBS) --bin $(APP) + +dev-test: dev-fast-check ## Run the test suite with Cranelift and mold + RUSTUP_TOOLCHAIN=$(DEV_FAST_TOOLCHAIN) $(CARGO) --config '$(DEV_FAST_CONFIG)' test --all-targets --all-features $(BUILD_JOBS) + +bench-build: dev-fast-check ## Time clean and incremental debug builds for both paths + @$(DEV_FAST_ENV) CARGO='$(CARGO)' scripts/bench-build.sh + help: ## Show available targets @grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \ awk 'BEGIN {FS=":"; printf "Available targets:\n"} {printf " %-20s %s\n", $$1, $$2}' diff --git a/scripts/bench-build.sh b/scripts/bench-build.sh new file mode 100755 index 000000000..6afcc160c --- /dev/null +++ b/scripts/bench-build.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# Benchmark the default (LLVM + platform linker) debug build against the opt-in +# mold + Cranelift path. +# +# Each variant is measured twice: a clean build from an empty target directory, +# and an incremental rebuild after touching the binary's entry point. Variants +# use separate target directories so neither warms nor invalidates the other's +# cache, and neither disturbs the working `target/` tree. Results are printed as +# a Markdown table so the developers' guide can be regenerated verbatim. + +set -euo pipefail + +script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=scripts/dev-fast-common.sh +. "$script_dir/dev-fast-common.sh" + +: "${CARGO:=cargo}" +: "${DEV_FAST_CONFIG:?DEV_FAST_CONFIG must be set}" + +BENCH_ROOT=${BENCH_ROOT:-target/bench} +BENCH_BIN=${BENCH_BIN:-netsuke} +BENCH_TOUCH_FILE=${BENCH_TOUCH_FILE:-src/main.rs} + +# Populated as "