11.PHONY : deps deps-linux deps-macos compile-programs-asm compile-programs-rust compile-bench \
2- compile-programs clean-asm clean-rust clean-bench clean-shared clean test test-asm \
2+ compile-programs compile-recursion-elfs clean-asm clean-rust clean-bench clean-shared \
3+ clean-recursion-elfs clean test test-asm \
34test-rust test-executor test-flamegraph flamegraph-prover \
45test-fast test-prover test-prover-all test-disk-spill test-math-cuda test-cuda-integration \
56bench-math-cuda bench-prover bench-prover-cuda build check clippy fmt lint regen-ethrex-fixtures \
@@ -46,6 +47,13 @@ BENCH_PROGRAM_DIRS := $(dir $(wildcard $(BENCH_PROGRAMS_DIR)/*/Cargo.toml))
4647BENCH_PROGRAMS := $(notdir $(basename $(BENCH_PROGRAM_DIRS:%/=% ) ) )
4748BENCH_ARTIFACTS := $(addprefix $(BENCH_ARTIFACTS_DIR ) /, $(addsuffix .elf, $(BENCH_PROGRAMS ) ) )
4849
50+ # Recursion smoke-test guests, in bench_vs/lambda/ (shared with bench_vs/run.sh)
51+ # rather than executor/programs/. The recursion guest is the in-VM STARK verifier.
52+ RECURSION_GUESTS_DIR =./bench_vs/lambda
53+ RECURSION_ARTIFACTS_DIR =./executor/program_artifacts/recursion
54+ RECURSION_GUESTS := empty fibonacci recursion
55+ RECURSION_ARTIFACTS := $(addprefix $(RECURSION_ARTIFACTS_DIR ) /, $(addsuffix .elf, $(RECURSION_GUESTS ) ) )
56+
4957# Override with: make ... SYSROOT_DIR=$HOME/.lambda-vm-sysroot
5058# to install the sysroot in a user-writable location and avoid sudo.
5159SYSROOT_DIR ?= /opt/lambda-vm-sysroot
@@ -133,7 +141,16 @@ compile-programs-rust: prepare-sysroot $(RUST_ARTIFACTS)
133141
134142compile-bench : prepare-sysroot $(BENCH_ARTIFACTS )
135143
136- compile-programs : compile-programs-asm compile-programs-rust compile-bench
144+ # NOTE: the recursion smoke tests are #[ignore]d (not run by `make test` /
145+ # `test-executor`) because they're too slow for CI today; only `test-prover-all`
146+ # runs them. We still compile their guest ELFs on every build so they keep
147+ # compiling until the tests are fast enough to run in CI.
148+ compile-programs : compile-programs-asm compile-programs-rust compile-bench compile-recursion-elfs
149+
150+ compile-recursion-elfs : prepare-sysroot $(RECURSION_ARTIFACTS )
151+
152+ $(RECURSION_ARTIFACTS_DIR ) :
153+ mkdir -p $@
137154
138155
139156$(RUST_ARTIFACTS_DIR ) :
@@ -142,34 +159,49 @@ $(RUST_ARTIFACTS_DIR):
142159$(BENCH_ARTIFACTS_DIR ) :
143160 mkdir -p $@
144161
162+ # The guest .elf rules depend on FORCE so their recipe always runs: cargo already
163+ # tracks the full dependency graph, so we let it decide what to rebuild (a fast
164+ # no-op when nothing changed) rather than re-encode that in Make prereqs.
165+ .PHONY : FORCE
166+ FORCE :
167+
168+ # The guest .elf rules all share one canned recipe: the cargo build invocation is
169+ # identical across the rust, bench, and recursion guests. They differ only in the
170+ # source directory ($(1)) and the built-binary name suffix ($(2): empty when the
171+ # binary == crate name, `-bench` for the recursion suite, whose crates are named
172+ # <name>-bench). cargo owns the dep graph (see FORCE above), so the recipe always
173+ # runs and lets cargo decide what to actually rebuild.
174+ define build_guest_elf
175+ cd $(1 ) /$* && \
176+ CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
177+ CFLAGS_riscv64im_lambda_vm_elf="$(SYSROOT_CFLAGS ) " \
178+ rustup run nightly-2026-02-01 cargo build --release \
179+ --target $(RV64_TARGET_SPEC ) \
180+ -Z build-std=core,alloc,std,compiler_builtins,panic_abort \
181+ -Z build-std-features=compiler-builtins-mem \
182+ -Z json-target-spec
183+ cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* $(2 ) $@
184+ endef
185+
145186# Compile rust (64-bit)
146187# Order-only `| prepare-sysroot` so a direct `make .../foo.elf` provisions the sysroot
147188# first (the aggregate compile-programs-rust/compile-bench targets already do, but a
148189# bare pattern-rule invocation like `make -B .../ethrex.elf` would otherwise skip it
149190# and fail to compile guest C dependencies). Order-only because prepare-sysroot is
150191# .PHONY — a normal prereq would force a rebuild every time; its recipe is idempotent.
151- $(RUST_ARTIFACTS_DIR ) /% .elf : $(RUST_PROGRAMS_DIR ) /% /Cargo.toml | prepare-sysroot $(RUST_ARTIFACTS_DIR )
152- cd $(RUST_PROGRAMS_DIR ) /$* && \
153- CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
154- CFLAGS_riscv64im_lambda_vm_elf=" $( SYSROOT_CFLAGS) " \
155- rustup run nightly-2026-02-01 cargo build --release \
156- --target $(RV64_TARGET_SPEC ) \
157- -Z build-std=core,alloc,std,compiler_builtins,panic_abort \
158- -Z build-std-features=compiler-builtins-mem \
159- -Z json-target-spec
160- cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* $@
192+ $(RUST_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(RUST_ARTIFACTS_DIR )
193+ $(call build_guest_elf,$(RUST_PROGRAMS_DIR ) ,)
161194
162195# Compile rust benches (64-bit)
163- $(BENCH_ARTIFACTS_DIR ) /% .elf : $(BENCH_PROGRAMS_DIR ) /% /Cargo.toml | prepare-sysroot $(BENCH_ARTIFACTS_DIR )
164- cd $(BENCH_PROGRAMS_DIR ) /$* && \
165- CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
166- CFLAGS_riscv64im_lambda_vm_elf=" $( SYSROOT_CFLAGS) " \
167- rustup run nightly-2026-02-01 cargo build --release \
168- --target $(RV64_TARGET_SPEC ) \
169- -Z build-std=core,alloc,std,compiler_builtins,panic_abort \
170- -Z build-std-features=compiler-builtins-mem \
171- -Z json-target-spec
172- cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* $@
196+ $(BENCH_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(BENCH_ARTIFACTS_DIR )
197+ $(call build_guest_elf,$(BENCH_PROGRAMS_DIR ) ,)
198+
199+ # Recursion-suite guests (bench_vs/lambda/): the crate's binary is <name>-bench, so
200+ # copy <name>-bench -> <name>.elf. std-inclusive build-std covers both the no_std
201+ # inner guests and the std recursion verifier. Prover tests read these prebuilt
202+ # artifacts like every other program (see prover/src/tests/recursion_smoke_test.rs).
203+ $(RECURSION_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(RECURSION_ARTIFACTS_DIR )
204+ $(call build_guest_elf,$(RECURSION_GUESTS_DIR ) ,-bench)
173205
174206clean-asm :
175207 -rm -rf $(ASM_ARTIFACTS_DIR )
@@ -183,7 +215,10 @@ clean-bench:
183215clean-shared :
184216 -rm -rf $(SHARED_TARGET_DIR )
185217
186- clean : clean-asm clean-rust clean-bench clean-shared
218+ clean-recursion-elfs :
219+ -rm -rf $(RECURSION_ARTIFACTS_DIR )
220+
221+ clean : clean-asm clean-rust clean-bench clean-shared clean-recursion-elfs
187222
188223test-executor : compile-programs
189224 cargo test -p executor
@@ -225,8 +260,9 @@ test-fast:
225260test-prover :
226261 cargo test -p lambda-vm-prover
227262
228- # Prover tests including slow ones
229- test-prover-all :
263+ # Prover tests including slow ones. The recursion smoke tests (#[ignore]d) read
264+ # prebuilt guest ELFs from executor/program_artifacts/recursion/, so build them first.
265+ test-prover-all : compile-recursion-elfs
230266 cargo test -p lambda-vm-prover -- --include-ignored
231267
232268# Prover tests with debug-checks (shows bus balance report)
0 commit comments