A release build links the agent package again
vendor/agent/flan_agent.c calls flan_dev_result_get, which lives in flan_dev.c, which build.ml compiled only for a dev build - so flan build sand.flan died at the link with an undefined symbol. A regression from 7ce1d09, where C-x C-e gave the agent a result to report. A package's C sources are collected whatever main does, so the agent's C is in every build that imports it. flan_dev.c is now compiled into all of them. Nothing in a release build reaches it: the compiler emits a registry lookup only for a name the host was not built with, and without cells there is no such name. The table is BSS, so the cost is address space rather than binary size, and -rdynamic and the cells are still what --dev means. test_agent.ml now links the same program both ways. It runs only the dev one - with no cells the agent refuses every module, so linking is the whole claim.
This commit is contained in:
parent
ec0d845822
commit
9e845fd980
11
NEXT.md
11
NEXT.md
@ -389,6 +389,17 @@ none. `Emit.signature` is now the single place a function's LLVM signature is
|
||||
spelled, because a `define` here and a `declare` there drift the moment one of
|
||||
them grows a case for `Unit` or for a slice parameter.
|
||||
|
||||
**`flan_dev.c` is compiled into every build, not only a dev one.** Nothing in a
|
||||
release build calls into it — the compiler only emits a registry lookup for a
|
||||
name the host was not built with, which cannot arise without cells — but the
|
||||
agent package's C refers to it, and a package's C sources are collected
|
||||
whatever `main` does. Leaving it out of release builds made `flan build
|
||||
sand.flan` fail at the link with an undefined `flan_dev_result_get`, which
|
||||
reads as a compiler bug rather than as a missing flag. The table is BSS, so the
|
||||
cost is address space and not binary size; `-rdynamic` and the cells are still
|
||||
what `--dev` means. `test_agent.ml` links the agent program both ways for this
|
||||
reason.
|
||||
|
||||
**`-rdynamic` is load-bearing.** A normal executable exports nothing: `nm -D
|
||||
calc-me | grep 'flan\.'` is empty, so a loaded module's `declare`s would have
|
||||
nothing to bind to. The test passes it through `lflags`, which keeps it a
|
||||
|
||||
13
lib/build.ml
13
lib/build.ml
@ -120,11 +120,18 @@ let executable ?(opts = default) ?(csrcs = []) ?(lflags = [])
|
||||
let dir = workdir () in
|
||||
let ll = Filename.concat dir (Filename.basename out ^ ".ll") in
|
||||
write ll (Emit.program ~checks:opts.checks ~dev:opts.dev p);
|
||||
(* [flan_dev.c] is compiled into every build, not only a dev one. Nothing in
|
||||
a release build calls into it — the compiler only emits a registry lookup
|
||||
for a name the host was not built with, which cannot arise without cells —
|
||||
but the agent package's C refers to it, and a package's C sources are
|
||||
collected whatever [main] does. Leaving it out made [flan build sand.flan]
|
||||
fail at the link with an undefined symbol, which reads as a compiler bug
|
||||
rather than as a missing flag. The table is BSS, so this costs address
|
||||
space and not binary size, and [-rdynamic] and the cells are still what
|
||||
[--dev] means. *)
|
||||
let objs =
|
||||
compile_c ~opts ~src:Runtime_src.source ~name:"flan_rt.c"
|
||||
:: (if opts.dev then
|
||||
[ compile_c ~opts ~src:Runtime_src.dev_source ~name:"flan_dev.c" ]
|
||||
else [])
|
||||
:: [ compile_c ~opts ~src:Runtime_src.dev_source ~name:"flan_dev.c" ]
|
||||
@ List.map
|
||||
(fun c ->
|
||||
compile_c ~opts ~src:(read_file c) ~name:(Filename.basename c))
|
||||
|
||||
@ -77,6 +77,19 @@ let () =
|
||||
(Build.executable ~opts:dev ~csrcs:l.Load.csrcs ~lflags:l.Load.lflags
|
||||
t.Session.host ~out:exe);
|
||||
|
||||
(* And the same program without [--dev], which has to *link*. A package's C
|
||||
sources are collected whatever [main] does, so the agent's C is in every
|
||||
build that imports it, and it refers to the dev runtime — leaving that
|
||||
out made this an undefined symbol at the link rather than a missing
|
||||
flag. Nothing is run: with no cells the agent refuses every module, and
|
||||
linking is the whole claim. *)
|
||||
(match
|
||||
Build.executable ~opts:Build.default ~csrcs:l.Load.csrcs
|
||||
~lflags:l.Load.lflags t.Session.host ~out:(tmp "prog-release")
|
||||
with
|
||||
| _ -> ()
|
||||
| exception Failure m -> fail "a release build of the agent: %s" m);
|
||||
|
||||
(* Two evaluations from the one session, which is the daemon's loop and
|
||||
the thing no earlier test does. The first introduces a global the
|
||||
process was never built with; the second only reads it, and can only
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user