Three things stood between the flagship program and the web target, and each is answered here rather than worked around. The brush was a path. (rl/load-texture "brush.png") hands raylib a filename to open, and a bare relative path means nothing on a target with no filesystem. It is (embed "brush.png") now, decoded through a new binding — LoadImageFromMemory, declared (Ptr u8) plus an explicit count because the shim generator refuses a slice parameter and says so, with a Flan wrapper taking the slice apart exactly as collision-point-poly? and load-font-ex already do. One decode now serves both textures: the unflipped upload first, then ImageFlipHorizontal in place, then the mirrored one. load-texture and load-image lose their only call site in this repository; that is deliberate, because a path-based load is the thing that cannot work here. A package's C may now be addressed to one target, the way a link line already could. A .c file may carry a tag before its extension — flan_agent.web.c — and on that target it is compiled and *replaces* the untagged file of the same base name. Replacement rather than plain tagging, so that teaching a package about a new target is additive: the file that was right on three targets is not renamed to say so. Selection is in Build and not in Load, for the reason select_lflags gives. The dev agent on the web is a no-op, and the reasoning is written at length in vendor/agent/flan_agent.web.c. Short version: the agent is a socket server and a browser has no sockets, so the missing <sys/time.h> was the surface and not the cause. Refusing vendor:agent on a web target was the other candidate and is ruled out by arithmetic — Flan has no conditional compilation, sand.flan calls agent/start unconditionally, Reach cannot prune a package something reachable calls into, so a refusal means the program does not build for the browser at all. This does not contradict the `barf` decision made earlier today. `barf` is asked to make something durable, and a no-op returns success to a program that now believes bytes are on disk. The agent is asked to accept redefinitions, and on the web there is no editor, no socket and no session — --dev is refused by name on every wasm target — so there is nothing to lose. sand.flan already says the same of a native release build at the call site. test/test_web.ml builds sand.flan for the browser and reads the module for brush.png's own bytes, whole. Not "IHDR": stb_image carries that string itself, linked in from raylib, so it would pass on a build where the embed emitted nothing. It is not run — node has no DOM, so main reaches InitWindow and dies inside glfwInit on `window is not defined`, which says the module is live and nothing about whether the canvas paints. test/dune gains brush.png, because an embed is read by the checker and the headless case reaches sand.flan through ../../ from a sandboxed _build. test_session's C-c C-k case now passes ~origin, which is what both editor paths already send; omitting it was testing a request nobody makes. dune test is green. Docs follow in the next commit.
105 lines
5.1 KiB
Plaintext
105 lines
5.1 KiB
Plaintext
(tests
|
|
(names test_flan test_acceptance test_reload test_agent test_session test_dev test_emacs test_repl test_cider)
|
|
; Explicit because test_sanitize lives in this directory and is not one of
|
|
; these: two stanzas in one directory have to say which modules are whose.
|
|
; watchdog is every binary's clock: a hanging test reports nothing, so each
|
|
; of these arms an alarm that turns "for ever" into a failing run.
|
|
(modules test_flan test_acceptance test_reload test_agent test_session
|
|
test_dev test_emacs test_repl test_cider watchdog)
|
|
(libraries flan unix)
|
|
; The acceptance programs are part of the test corpus: if the reader, the
|
|
; parser or the checker regresses on them we want to know here, not at the CLI.
|
|
(deps
|
|
(file %{workspace_root}/calc-me.flan)
|
|
(file %{workspace_root}/sand.flan)
|
|
; The brush sheet, which sand.flan now (embed ...)s rather than opening by
|
|
; path. An embed is read by the *checker*, relative to the file the form is
|
|
; written in, so it is a dependency of every build of sand.flan including the
|
|
; headless one — which reaches sand.flan through ../../ from programs/ and
|
|
; would otherwise find nothing at _build/default/brush.png.
|
|
(file %{workspace_root}/brush.png)
|
|
; The raylib bindings, because sand.flan and the FFI case import them and an
|
|
; import reads the directory at build time. sand.flan itself is above: the
|
|
; headless case imports it as a single-file package.
|
|
(glob_files %{workspace_root}/vendor/raylib/*)
|
|
; The dev agent package: its Flan declarations and the C that implements them.
|
|
(glob_files %{workspace_root}/vendor/agent/*)
|
|
; The EDN tokenizer, which programs/edn.flan imports.
|
|
(glob_files %{workspace_root}/vendor/edn/*)
|
|
; The ported raylib examples. Only one of them has a headless acceptance
|
|
; case, but it imports its example as a package and that example imports
|
|
; examples/digits.flan, so the directory has to be here whole.
|
|
(glob_files %{workspace_root}/examples/*)
|
|
(glob_files programs/*.flan)
|
|
; The files programs/embed.flan bakes in. An embed reads them at *compile*
|
|
; time, so they are a dependency of the checker run and not of the program.
|
|
(glob_files programs/assets/*)
|
|
; The reload primitive's host: a C main that dlopens what Build.shared made.
|
|
(file reload_host.c)
|
|
; A shared object that is not a redefinition module, for the agent's refusal
|
|
; path. Its destructor is what proves the handle was closed rather than lost.
|
|
(file noinstall.c)
|
|
; The other C main: flan_dev.c's two fixed limits, which no Flan program
|
|
; reaches, driven directly.
|
|
(file dev_limits.c)
|
|
; test_dev runs the compiler itself: flan dev launches and owns a program.
|
|
(file %{workspace_root}/bin/main.exe)
|
|
; The Emacs client, which test_emacs drives against a real daemon.
|
|
(glob_files %{workspace_root}/emacs/*.el)
|
|
; The WASI host the wasm32 case runs its module under, when no wasmtime or
|
|
; wasmer is installed.
|
|
(file wasm-run.mjs)))
|
|
|
|
; The web target, in its own stanza rather than in the table above because it
|
|
; is the one case whose toolchain is a separate install: emscripten, and a
|
|
; raylib archive built by vendor/raylib/build-web.sh. It probes for both and
|
|
; skips with the reason, so it is green on a machine that has neither.
|
|
(test
|
|
(name test_web)
|
|
(modules test_web)
|
|
(libraries flan unix)
|
|
(deps
|
|
(glob_files programs/*.flan)
|
|
(glob_files programs/assets/*)
|
|
; The raylib bindings and the ported example the raylib case builds. The
|
|
; example imports examples/digits.flan, so the directory comes whole.
|
|
(glob_files %{workspace_root}/vendor/raylib/*)
|
|
(glob_files %{workspace_root}/examples/*)
|
|
; sand.flan for the browser, with the sheet it embeds and the dev agent it
|
|
; imports — the agent's directory has to be whole, because the file that
|
|
; makes a web build possible is the one Build selects out of it.
|
|
(file %{workspace_root}/sand.flan)
|
|
(file %{workspace_root}/brush.png)
|
|
(glob_files %{workspace_root}/vendor/agent/*)
|
|
; flan run --target=web is refused by the CLI, so the CLI has to be here.
|
|
(file %{workspace_root}/bin/main.exe)))
|
|
|
|
; The corpus a second time under ASan and UBSan. Its own alias and not part of
|
|
; `dune test`: a sanitized build is a statically linked 1.8MB binary that takes
|
|
; tens of seconds to produce, so the sweep is minutes against the existing
|
|
; suite's seconds, and a test nobody will wait for is a test nobody runs.
|
|
;
|
|
; dune build --root . @sanitize
|
|
; An executable plus a rule rather than a (test ...): a test stanza attaches
|
|
; to the @runtest alias and offers no way to be attached to another one, which
|
|
; is the whole point here.
|
|
(executable
|
|
(name test_sanitize)
|
|
(modules test_sanitize watchdog)
|
|
(libraries flan unix))
|
|
|
|
(rule
|
|
(alias sanitize)
|
|
(deps
|
|
test_sanitize.exe
|
|
(file %{workspace_root}/calc-me.flan)
|
|
(file %{workspace_root}/sand.flan)
|
|
(file %{workspace_root}/brush.png)
|
|
(glob_files %{workspace_root}/vendor/raylib/*)
|
|
(glob_files %{workspace_root}/vendor/agent/*)
|
|
(glob_files %{workspace_root}/vendor/edn/*)
|
|
(glob_files %{workspace_root}/examples/*)
|
|
(glob_files programs/*.flan)
|
|
(glob_files programs/assets/*))
|
|
(action (run ./test_sanitize.exe)))
|