jolt build: bundle native libs + resources into standalone binaries
A built binary dropped its deps.edn :jolt/native declarations and its
resource roots, so an FFI+resources app (ring-app) failed at runtime:
sockets/sqlite gave 'no entry for socket' and io/resource returned nil.
The buildsmoke fixture is pure compute, so neither path was exercised.
The launcher now loads required + :process native libs before the app's
top-level forms (a library's defcfn resolves its foreign-procedure symbols
at top-level eval during startup, so the libs must be loaded first);
optional libs load in the scheme-start launcher, where a missing lib is
caught rather than aborting the heap build.
deps.edn :jolt/build {:embed [dirs]} bakes those dirs' files into the heap
(register-embedded-resource! at heap build), so io/resource serves them with
no files on disk. Non-embedded resources resolve at runtime against JOLT_PWD,
and io/file reads (e.g. config.edn) stay external.
build-binary now takes the encoded natives, embed dirs, and project paths
from cmd-build; deps/resolve-project surfaces them. Buildsmoke fixture grows
an embedded resource + a :process native to cover both paths.
This commit is contained in:
parent
22c08d30f2
commit
1d345bfd0f
10 changed files with 227 additions and 36 deletions
|
|
@ -56,11 +56,41 @@ roots, and de-sugars the argv into a run:
|
|||
- `-A:alias` → add the alias's paths/deps, then run the rest;
|
||||
- `repl` → a line REPL;
|
||||
- `path` → print the resolved roots;
|
||||
- `build -m NS [-o OUT] [--opt|--dev]` → AOT-compile the app into a standalone binary;
|
||||
- `<task>` → run a `deps.edn` `:tasks` entry.
|
||||
|
||||
The resolver lives in the overlay alongside the runtime, but the runtime's only
|
||||
dependency interface is the list of source roots it's handed.
|
||||
|
||||
## Native libraries
|
||||
|
||||
A library that binds C declares the shared objects it needs under `:jolt/native`,
|
||||
so `jolt.main` loads them before the namespace is required and its `foreign-fn`
|
||||
bindings resolve. Each entry is a map — `{:name "sqlite3" :darwin
|
||||
["libsqlite3.0.dylib" …] :linux ["libsqlite3.so.0" …]}` — with optional
|
||||
`:optional true` (absence is fine, a feature-gated dep) and `:process true` (use
|
||||
the running process's own symbols, e.g. libc sockets, no external file). A
|
||||
project inherits its dependencies' `:jolt/native`.
|
||||
|
||||
## Standalone binaries
|
||||
|
||||
`joltc build -m NS -o OUT` compiles the app and every library into one
|
||||
executable (the runtime + compiler are baked in). It loads the resolved
|
||||
`:jolt/native` libs at startup, so an FFI app — sockets, SQLite — runs with no
|
||||
jolt or Chez on the path.
|
||||
|
||||
`:jolt/build {:embed ["resources" …]}` bakes those directories' files into the
|
||||
binary; `io/resource` serves them from the image with no files on disk. Resources
|
||||
not embedded resolve at runtime against `JOLT_PWD` (or the cwd), so the
|
||||
ship-the-binary-with-its-`resources/`-dir model also works. Files read through
|
||||
`io/file` (e.g. a `config.edn` a config library loads) stay external by design —
|
||||
edit them without rebuilding.
|
||||
|
||||
A standalone build needs Chez's kernel dev files (`libkernel.a`, `scheme.h`) and
|
||||
a C compiler; `JOLT_CHEZ_CSV` overrides the auto-detected `csv<ver>/<machine>`
|
||||
dir. `--opt` turns on the inference/flatten/scalar-replace passes; the default
|
||||
`release` mode is const-fold only.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Pure `clj`/`cljc` only — JVM interop, host classes, and unimplemented
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue