3.2 KiB
Handoff — the linker error dune test prints on every run
Branch: dev-loop, worktree agent-a4f73ab1c6726fdc2. Scope is the dev-robust fixture and the noise it makes;
nothing else in the suite is touched.
The question
Every dune test --root . prints, twice:
/usr/bin/ld: cannot open output file /tmp/build_*_dune/flan-devtest-robust.cache/flan-macros-*.so.*: Permission denied
clang: error: linker command failed with exit code 1
HANDOFF-x86-rt.md section 4 says this is inside the dev-robust fixture and deliberate. That has been quoted
forward without ever being checked. The brief names two possibilities: the failure is deliberate and only looks
like a broken toolchain, or it is accidental and the fixture has been proving less than it claims.
The answer: deliberate, and the read is confirmed at the source
test/test_dev.ml, the block starting "A build that fails is a refusal, not the end of the session" (~line 2805):
- The fixture gives the daemon a cache directory of its own —
FLAN_CACHE_DIR=<tmp>/flan-devtest-robust.cache, with any inheritedFLAN_CACHE_DIRfiltered out of the environment first. - Before each step that must fail it runs
Unix.chmod rcache 0o500, and afterwards0o700. A read-only, non-writable cache directory is exactly whyldcannot open its output there. - The two failing steps are the
eval-exprone (C-x C-e) and theevalone carrying adefmacro(C-c C-c) — which is why the message appears twice per run, and why the count matches.
So this is possibility 1. The property — a failed build leaves the session standing — is genuinely under test.
The actual defect, which is narrower
The daemon is spawned with Unix.stderr as its stderr, so it inherits the test binary's. Build.run shells out
with Sys.command, which does not capture anything, so clang's and ld's own words go straight through to the
terminal. Its stdout already goes to a log file nobody reads (rout), and the comment there says as much; its
stderr was simply never given the same treatment.
The result is four lines of what reads like a broken toolchain on a passing run. A real linker failure in that spot today would be invisible.
The plan
- Give the robustness daemon its own stderr log rather than the suite's, the same way its stdout already has one.
- Report that log — and say so — only when something in the block actually failed, so a genuine linker error is still visible, and a deliberate one is not.
- Have the fixture announce the deliberate failure in its own voice before it causes it, so a reader of the output knows a build is about to be made to fail and why.
Baseline to not regress: dune test --root . exit 0, spike/x86/survey.sh 101 MATCH / 0 DIFFER / 0 refused,
spike/x86/cells.sh 4/4.
Open questions
Build.runreports only(exit N)to the caller; clang's actual words reach the terminal and nothing else. The fixture asserts the reply "carries the compiler's message" but only checks for the substring(exit, so an editor attached to a realflan devsees a bare exit status and no diagnostic. WideningBuild.runto capture and forward stderr would fix that, and is out of this lane's scope — recorded here so it is not lost.