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,12 @@ 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+ compile-programs : compile-programs-asm compile-programs-rust compile-bench compile-recursion-elfs
145+
146+ compile-recursion-elfs : prepare-sysroot $(RECURSION_ARTIFACTS )
147+
148+ $(RECURSION_ARTIFACTS_DIR ) :
149+ mkdir -p $@
137150
138151
139152$(RUST_ARTIFACTS_DIR ) :
@@ -142,13 +155,19 @@ $(RUST_ARTIFACTS_DIR):
142155$(BENCH_ARTIFACTS_DIR ) :
143156 mkdir -p $@
144157
158+ # The guest .elf rules depend on FORCE so their recipe always runs: cargo already
159+ # tracks the full dependency graph, so we let it decide what to rebuild (a fast
160+ # no-op when nothing changed) rather than re-encode that in Make prereqs.
161+ .PHONY : FORCE
162+ FORCE :
163+
145164# Compile rust (64-bit)
146165# Order-only `| prepare-sysroot` so a direct `make .../foo.elf` provisions the sysroot
147166# first (the aggregate compile-programs-rust/compile-bench targets already do, but a
148167# bare pattern-rule invocation like `make -B .../ethrex.elf` would otherwise skip it
149168# and fail to compile guest C dependencies). Order-only because prepare-sysroot is
150169# .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 )
170+ $(RUST_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(RUST_ARTIFACTS_DIR )
152171 cd $(RUST_PROGRAMS_DIR ) /$* && \
153172 CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
154173 CFLAGS_riscv64im_lambda_vm_elf=" $( SYSROOT_CFLAGS) " \
@@ -160,7 +179,7 @@ $(RUST_ARTIFACTS_DIR)/%.elf: $(RUST_PROGRAMS_DIR)/%/Cargo.toml | prepare-sysroot
160179 cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* $@
161180
162181# Compile rust benches (64-bit)
163- $(BENCH_ARTIFACTS_DIR ) /% .elf : $( BENCH_PROGRAMS_DIR ) / % /Cargo.toml | prepare-sysroot $(BENCH_ARTIFACTS_DIR )
182+ $(BENCH_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(BENCH_ARTIFACTS_DIR )
164183 cd $(BENCH_PROGRAMS_DIR ) /$* && \
165184 CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
166185 CFLAGS_riscv64im_lambda_vm_elf=" $( SYSROOT_CFLAGS) " \
@@ -171,6 +190,22 @@ $(BENCH_ARTIFACTS_DIR)/%.elf: $(BENCH_PROGRAMS_DIR)/%/Cargo.toml | prepare-sysro
171190 -Z json-target-spec
172191 cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* $@
173192
193+ # Recursion-suite guests: same standard guest flags as compile-bench (std-inclusive
194+ # build-std works for both the no_std inner guests and the std recursion verifier).
195+ # The crate's binary is <name>-bench; copy it to <name>.elf so prover tests read
196+ # prebuilt artifacts like every other program (see
197+ # prover/src/tests/recursion_smoke_test.rs), instead of shelling out.
198+ $(RECURSION_ARTIFACTS_DIR ) /% .elf : FORCE | prepare-sysroot $(RECURSION_ARTIFACTS_DIR )
199+ cd $(RECURSION_GUESTS_DIR ) /$* && \
200+ CARGO_TARGET_DIR=$(abspath $(SHARED_TARGET_DIR ) ) \
201+ CFLAGS_riscv64im_lambda_vm_elf=" $( SYSROOT_CFLAGS) " \
202+ rustup run nightly-2026-02-01 cargo build --release \
203+ --target $(RV64_TARGET_SPEC ) \
204+ -Z build-std=core,alloc,std,compiler_builtins,panic_abort \
205+ -Z build-std-features=compiler-builtins-mem \
206+ -Z json-target-spec
207+ cp $(SHARED_TARGET_DIR ) /riscv64im-lambda-vm-elf/release/$* -bench $@
208+
174209clean-asm :
175210 -rm -rf $(ASM_ARTIFACTS_DIR )
176211
@@ -183,7 +218,10 @@ clean-bench:
183218clean-shared :
184219 -rm -rf $(SHARED_TARGET_DIR )
185220
186- clean : clean-asm clean-rust clean-bench clean-shared
221+ clean-recursion-elfs :
222+ -rm -rf $(RECURSION_ARTIFACTS_DIR )
223+
224+ clean : clean-asm clean-rust clean-bench clean-shared clean-recursion-elfs
187225
188226test-executor : compile-programs
189227 cargo test -p executor
@@ -225,8 +263,9 @@ test-fast:
225263test-prover :
226264 cargo test -p lambda-vm-prover
227265
228- # Prover tests including slow ones
229- test-prover-all :
266+ # Prover tests including slow ones. The recursion smoke tests (#[ignore]d) read
267+ # prebuilt guest ELFs from executor/program_artifacts/recursion/, so build them first.
268+ test-prover-all : compile-recursion-elfs
230269 cargo test -p lambda-vm-prover -- --include-ignored
231270
232271# Prover tests with debug-checks (shows bus balance report)
0 commit comments