A compiler warning fails the build, so a test's verdict depends on whether its TU was recompiled #32
Labels
No labels
bug
claude:blocked
claude:done
claude:failed
claude:in-progress
claude:ready
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Catcrafts/Crafter.Build#32
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A compiler warning fails the build, because success is inferred from whether
the compiler printed anything rather than from its exit code. Warnings are only
emitted when a translation unit is actually recompiled, so the same unchanged
source passes or fails depending on whether its object file happened to be
up to date.
Impact
It presents as flaky tests, and it is very convincing: a test "fails", you
re-run it, it passes, and you conclude the first result was a stale artifact or
a race. I misdiagnosed it three times in one session before reading the source —
twice writing it off as a stale build tree, once filing it in my own notes as an
intermittent crash.
The failure mode is worst exactly where it costs most:
module interface, a
clean, a fresh CI checkout — surfaces every latentwarning in the project at once, as a wall of unrelated test failures.
builds pass. The reverse of the usual "works on my machine".
(0ms)andexit -1in the output read like the binary failed to launch,not like a compile diagnostic. The reason is printed, but on indented
continuation lines that are easy to filter out or lose in a parallel run's
interleaved output.
Reproducer
A project with one test whose source emits a warning and returns 0:
project.cpptests/ShouldPassDespiteWarning/main.cpp-Wtrigraphsis convenient because it is on by default at the flags this builduses; any enabled-by-default warning does the same thing.
Diagnosis
RunCommandmerges stderr into stdout and returns the combined text, throwingaway
pclose's status (implementations/Crafter.Build-Platform.cpp:764):Every caller then treats "printed something" as "failed". For a test's
main.cppthat isimplementations/Crafter.Build-Implementation.cpp:55:The same shape is in
Crafter.Build-Interface.cpp:82,97,206,221(precompile andobject steps),
Crafter.Build-Clang.cpp:791(C),:815(CUDA) and:1168-1232(every link / archive / shared-library step), and it surfaces to tests at
Crafter.Build-Test.cpp:657:Note that the link steps are covered too, so a linker warning fails a build the
same way.
Suggested fix
RunCommandCheckedsits directly belowRunCommandin the same file(
Crafter.Build-Platform.cpp:784) and already captures the exit code, thesignal and the crash flag:
So the compile and link sites can switch to it and branch on
exitCode != 0,keeping
outputfor display. That also fixes a second, quieter problem: today acompiler that is killed (OOM, for instance) but printed nothing is treated
as success, and the build proceeds with a missing object.
Whether warnings should still be shown on a successful build is a separate
question — printing them without failing would be a strict improvement, since
right now a warning on an incremental build is invisible until the next cold
one.
A note on intent
If failing on warnings is deliberate, the current behaviour still isn't it: a
policy that only applies when a file happens to be recompiled is not a policy.
Making it explicit and consistent —
-Werrorin the compile flags, failing onthe exit code — would fail the same way every time, which is the part that
matters. The current arrangement is the worst of both: warnings are fatal, but
only sometimes, and the resulting failure looks like something else entirely.
Environment
Crafter.Buildat046b5ee, clang 22.1.8, x86_64-pc-linux-gnu, libc++.after dependency bumps.