`headers` beside `link`, read the same way: a path, any clang flags that header
needs, ${NAME} expanded from the environment. What comes back is ordinary
declare-c declarations, generated before the package's names are qualified, so
they arrive as rl/… exactly like the hand-written ones and nothing downstream
can tell which is which. No new form, no new decl_kind, no reader or parser
change.
A leading `?` makes a line optional. vendor/raylib uses it, because "a build
needs libraylib linkable and not raylib-devel installed" is a property worth
keeping — requiring a header would take it from everyone to give the check to
whoever has one. Unset FLAN_RAYLIB_H and the build is exactly what it was; set
it and every signature is checked against raylib's own header.
A C symbol the package already binds by hand is left alone, so declare-c
remains the escape hatch and stays the thing that wins. A refused function
becomes a hidden name through Load.refuse_hidden, so writing rl/get-gamepad-name
says "GetGamepadName returns char *, and a string only crosses as a parameter"
rather than "unknown name".
Measured, because the cost is the whole argument for how much to import:
release build +14ms cold, +4ms warm — Reach prunes the wrappers
redefinition 31ms -> 46.5ms
dev build +333ms cold — dev does not prune, 428 wrappers
Reach.link already drops a generated wrapper whose declaration nothing
reachable calls, and that is what makes a wholesale import cost nothing in a
release build. It does not prune dev builds, on purpose, so a dev build
compiles every wrapper once at session start; Build.shared compiles no C, so
redefinition does not pay that again.
Reading the header is cached — 64ms of a 72ms check, against 8ms for the whole
program without it. Keyed like the object cache, on everything that could
change the answer: the header's path, size and mtime, the full flag list, and a
format version, since the cached value is a marshalled dump. The extracted
signatures are cached rather than clang's JSON, because the parse is half the
cost. That takes the delta to 17ms.
Verified end to end and headless, using only imported declarations:
ColorToInt of {17,34,51,68} is 0x11223344 and ColorTint hands the four bytes
back separately, so field order is pinned by arithmetic rather than by a
round trip. TextLength of "hello" is 5, so the string crossing works.
33 lines
1.6 KiB
Plaintext
33 lines
1.6 KiB
Plaintext
# C headers this package reads function signatures out of. One per line: a
|
|
# path, then any clang flags that header needs. A relative path is against
|
|
# this directory, ${NAME} expands from the environment, and a leading `?`
|
|
# means "if it is there" — an optional line with nothing behind it is simply
|
|
# not read.
|
|
#
|
|
# Why this exists. The declare-c lines in raylib.flan were transcribed by
|
|
# hand from raylib's documentation, and until now nothing could check that
|
|
# any of them matched the real function — BUILT.md records that as trusted
|
|
# rather than guaranteed. Point this at raylib's own header and the compiler
|
|
# reads the signatures instead: every hand-written line is compared against
|
|
# the library's, every defstruct against the header's record, and any raylib
|
|
# function the package has not bound becomes available under its own name.
|
|
#
|
|
# Why it is optional. A build needs libraylib linkable and *not* raylib-devel
|
|
# installed, which is a property worth keeping; requiring a header would take
|
|
# it from everyone to give the check to whoever has one. So the default build
|
|
# is unchanged and this is opt-in, the same shape as ${FLAN_RAYLIB_WEB} in
|
|
# `link`.
|
|
#
|
|
# The version must match the shared library `link` names — 5.5, libraylib.so.550.
|
|
# Reading one version's header while linking another's library is exactly the
|
|
# silent disagreement this exists to prevent, and `flan import-c` will say so:
|
|
# against a 5.1-dev header it reports ten differences that are all real.
|
|
#
|
|
# export FLAN_RAYLIB_H=/path/to/raylib-5.5/src/raylib.h
|
|
#
|
|
# To see what it would do without building anything:
|
|
#
|
|
# flan import-c $FLAN_RAYLIB_H vendor/raylib/raylib.flan
|
|
#
|
|
?${FLAN_RAYLIB_H}
|