flan/test/programs/pkg-unused.flan
Joseph Ferano 0e88954664 The link follows the program, not the import list
A package handed over its .c files and its `link` arguments the moment it was
imported, whatever the importing program did with it. That is what made sand's
two halves two files: anything naming vendor:raylib linked libraylib on every
target, and on wasm32 that link cannot succeed, so the headless run could not
so much as mention the package the interactive one needs.

Reach.link answers it from the checked program instead. Start at main and at
the globals that run before it, follow every call — including the Handled
frames, where a lifted handler clause is reached by address and by nothing
else — and keep what is reached. A package none of whose externs survive
contributes no C and no linker argument.

Dropping the flags alone would only move the failure: the bodies that called
into raylib would still be emitted, and wasm-ld would fail on the symbols
rather than on the argument. So the same walk prunes the functions and externs
too. Only those — globals, structs and unions stay, because an unreferenced
global is bytes in BSS and a dropped one is a silently different program.

Dev builds keep everything. What a REPL may redefine next is not a function of
what has been called so far.
2026-09-11 20:02:21 +07:00

13 lines
417 B
Plaintext

;;;; A package imported and never called into.
;;;;
;;;; raylib is here, so before Reach.link this program linked libraylib — and
;;;; on wasm32 it could not be built at all. The link now follows what the
;;;; program reaches rather than what it imports, so main's one print is the
;;;; whole of it and the same file builds for both targets.
(import rl "vendor:raylib")
(defn main [] i32
(print-line "ok")
0)