The acceptance case stops asking for a header it no longer needs

The imported-bindings program was skipped without FLAN_RAYLIB_H, which was
right when the bindings only existed if a header was read and is now the one
gate hiding the change. It runs on the same terms as every other raylib case:
libraylib linkable, no raylib-devel. A generated.flan regenerated empty or
stale is now caught on an ordinary machine rather than only on one with a
header exported.

Reach.link already answers the shim worry BUILT.md's cold-build attribution
would otherwise raise: sand.flan links 110 wrappers, not 425, because the
bindings nothing reachable calls are dropped. What is left is 65ms of frontend
on a cold build, against a header read that was 60-90ms of a fresh session and
15.5ms of every redefinition. Both numbers are in BUILT.md now.

Also a swallowed line continuation in the exclusion message.
This commit is contained in:
Joseph Ferano 2026-09-13 08:22:10 +07:00
parent 65fd49f0c6
commit 7332bed14a
3 changed files with 48 additions and 18 deletions

View File

@ -437,6 +437,37 @@ split this change exists to remove. The C symbol is kept verbatim in
`Ast.DeclareC` either way, so a rename costs nothing: it is still what is
called and still what the check compares against.
#### What committing 253 more declarations costs, measured
The section above says the cost is the check. That is the cost that mattered,
but it is not the only one, and this file does not omit measured numbers.
Every build now carries 425 `declare-c` where a default build carried 172, and
the obvious worry is the shim: BUILT.md's own cold-build attribution above
blames "the object cache compiling a shim with 428 wrappers in it", and that
was the *opt-in* path. It is not what happens, because `Reach.link` drops the
bindings nothing reachable calls and the shim comes back in parts for exactly
that purpose. `sand.flan` links **110** wrappers, not 425 — `nm sand | grep -c
flan_shim_`. A program that never draws still compiles no drawing wrapper.
(`flan shim <file>` prints the unpruned view, so it says 427 and is not the
number a build pays.)
What is left is frontend work on 253 more declarations, and it is small:
| cold build of `sand.flan`, object cache cleared | best of 3 |
|---|---|
| 425 declarations (committed bindings) | 2.16s |
| 172 declarations (`generated.flan` moved aside) | 2.10s |
**+65ms, about 3%, and cold only** — the object cache serves the shim after one
build, and the redefinition path never recompiles C at all. Against it: the
header read this removes was 6090ms of a fresh session by the measurement
above, and DISCUSS.md 6a measured it at 15.5ms on *every* redefinition, which is
a 50% increase on the number the dev-loop lane exists to keep small. So for
anyone who had the opt-in switched on this is a straight win, and for everyone
else it is 65ms once per cold build in exchange for 253 bindings that were
previously unreachable.
Two bindings the config cannot express stay hand-written, and they are the
reason `declare-c` remains the escape hatch: `LoadFontEx` and
`LoadImageFromMemory` are bound `-raw` and wrapped by a Flan function of the

View File

@ -639,7 +639,8 @@ let of_dump ~env ~taken ~bound_syms ~config (d : dump) : imported =
hidden :=
(flan_name config f.csym,
Printf.sprintf
"%s is excluded by the package's binding config, so no declaration is generated for it" f.csym)
"%s is excluded by the package's binding config, so no \
declaration is generated for it" f.csym)
:: !hidden)
dropped;
let groups = Hashtbl.create 512 in

View File

@ -802,23 +802,21 @@ let () =
TextLength of "hello" is 5, which is only true if the generated wrapper
NUL-terminated the copy.
Skipped without FLAN_RAYLIB_H, because the import is opt-in a build
needs libraylib linkable and not raylib-devel installed, and that is a
property worth keeping. The importer's own table does not skip: it runs
against test/headers/sample.h, which is committed. *)
(match Sys.getenv_opt "FLAN_RAYLIB_H" with
| Some h when Sys.file_exists h
&& Sys.command "ldconfig -p 2>/dev/null | grep -q libraylib" = 0 ->
let out = "10\n5\n287454020\n17\n34\n51\n68\n" in
outputs "raylib, bindings read from the header" "programs/raylib-imported.flan" out;
(* At -O0 too, for the reason the rest of the table is: every struct
here crosses as (addr v) on a local, which is the alloca mem2reg
would launder before anyone noticed it was wrong. *)
outputs ~opt:"-O0" "raylib, bindings read from the header, -O0"
"programs/raylib-imported.flan" out
| _ ->
print_endline
"acceptance: skipping the imported-bindings case (FLAN_RAYLIB_H unset)");
This used to be skipped without FLAN_RAYLIB_H, because the generated
bindings only existed when a header was read. They are committed now
vendor/raylib/generated.flan so it runs on the same terms as every
other raylib case here: libraylib linkable, and no raylib-devel. That is
the change stated as a test rather than as a claim. If generated.flan
were ever regenerated empty or stale, this is what would say so, and it
would say so on an ordinary machine rather than only on one with a
header exported. *)
let out = "10\n5\n287454020\n17\n34\n51\n68\n" in
outputs "raylib, bindings generated from the header" "programs/raylib-imported.flan" out;
(* At -O0 too, for the reason the rest of the table is: every struct
here crosses as (addr v) on a local, which is the alloca mem2reg
would launder before anyone noticed it was wrong. *)
outputs ~opt:"-O0" "raylib, bindings generated from the header, -O0"
"programs/raylib-imported.flan" out;
(* raylib's Image family, headless, and the strongest FFI case here: an
Image is pixels in RAM, so raylib *computes* with it rather than