81 lines
3.6 KiB
Plaintext
81 lines
3.6 KiB
Plaintext
(library
|
|
(name flan)
|
|
(libraries unix)
|
|
; -linkall because lib/macro.ml installs itself into Parse.expander at module
|
|
; initialisation and nothing references it. Without it the linker drops the
|
|
; module from every executable that does not name it -- bin/main.exe among
|
|
; them -- and a program calling a macro would fail with an unknown name
|
|
; instead of expanding. The alternative was an install call at every entry
|
|
; point, including ones in files this cannot reach.
|
|
(library_flags (-linkall))
|
|
; Running a macro means dlopening it into the compiler, and OCaml has no
|
|
; dlopen for ELF -- Dynlink loads OCaml. These are the stubs for it, and the
|
|
; only C the compiler itself is built from. See lib/dynload_stubs.c.
|
|
(foreign_stubs
|
|
(language c)
|
|
(names dynload_stubs spawn_stubs))
|
|
; No (c_library_flags (-ldl)): since glibc 2.34 dlopen lives in libc itself
|
|
; and libdl is a stub, and naming it breaks the merged build -- the partial
|
|
; link -output-complete-obj performs cannot resolve -ldl, so `flan dev` in
|
|
; one process fails at the link with "cannot find -ldl" while the ordinary
|
|
; build is unaffected. Add it back only with a platform guard.
|
|
)
|
|
|
|
; The host shim is Flan's, not the user's, so the compiler carries it rather
|
|
; than looking for it in an install directory. Generated from the real .c files
|
|
; so there is only ever one copy to edit. flan_dev.c goes into a dev build
|
|
; only — it is the run-time name lookup a REPL needs and a release build has
|
|
; no use for.
|
|
;
|
|
; flan_dyn.c is the third: the dynamic-value runtime, tagged values and the
|
|
; mark-sweep heap under them. It is carried the same way and for the same
|
|
; reason, and it is a *separate* string rather than being appended to
|
|
; [source] because it has to stay a separate translation unit — a program that
|
|
; calls no dyn operation references no symbol in it, which is what lets a
|
|
; build refuse to link it at all. See docs/SPIKE-DYNAMIC.md.
|
|
(rule
|
|
(target runtime_src.ml)
|
|
(deps
|
|
%{workspace_root}/runtime/flan_rt.c
|
|
%{workspace_root}/runtime/flan_dev.c
|
|
%{workspace_root}/runtime/flan_dyn.c
|
|
%{workspace_root}/runtime/flan_dyn.h
|
|
%{workspace_root}/vendor/agent/flan_agent.c)
|
|
(action
|
|
(with-stdout-to
|
|
runtime_src.ml
|
|
(progn
|
|
(echo "let source = {c|\n")
|
|
(cat %{workspace_root}/runtime/flan_rt.c)
|
|
(echo "|c}\n\nlet dev_source = {c|\n")
|
|
(cat %{workspace_root}/runtime/flan_dev.c)
|
|
(echo "|c}\n\nlet dyn_source = {c|\n")
|
|
(cat %{workspace_root}/runtime/flan_dyn.c)
|
|
; And the header, which is *not* compiled: it is written into the
|
|
; directory each translation unit is compiled in, so that a package's C —
|
|
; and test/dyn_ops.c — can include it. flan_dyn.c does not include it and
|
|
; declares its own prototypes instead, because the object cache is keyed
|
|
; on the source text and a header change would not invalidate an object
|
|
; compiled against the old one.
|
|
(echo "|c}\n\nlet dyn_header = {c|\n")
|
|
(cat %{workspace_root}/runtime/flan_dyn.h)
|
|
; And the agent's C, which flan dev links into every program it builds
|
|
; whether or not the source imports the package. See [Dev.with_agent].
|
|
(echo "|c}\n\nlet agent_source = {c|\n")
|
|
(cat %{workspace_root}/vendor/agent/flan_agent.c)
|
|
(echo "|c}\n")))))
|
|
|
|
; The prelude, carried the same way: lib/prelude.fln is the source, read by
|
|
; the indented reader at every build (lib/prelude.ml). No newline after the
|
|
; opening quote, so a location's line is the file's line.
|
|
(rule
|
|
(target prelude_src.ml)
|
|
(deps prelude.fln)
|
|
(action
|
|
(with-stdout-to
|
|
prelude_src.ml
|
|
(progn
|
|
(echo "let source = {fln|")
|
|
(cat prelude.fln)
|
|
(echo "|fln}\n")))))
|