Expand description
Runtime dependencies: the [dependencies] schema in lumen.toml, and
the loader that brings each declared library into the app at startup.
One table declares two kinds, told apart at load by the symbols the file
exports (see loader):
- An engine-locked runtime module is an ordinary
lumen_core::app::Pluginbuilt as a shared library that links the engine dynamically (lumen-dylib). The loader opens it, verifies it against the running engine, and calls its install entry, which registers real systems, components, and resources into the same ECS worlds the app runs on. - A portable plugin is a C-ABI cdylib (
lumen-plugin) exchanging serialized bytes: script functions, language preludes, and events. It needs no dynamic engine and loads into static hosts too.
A module the binary was built with takes neither path. It has no file to
open, so its constructor put its install entry on the registry before
main, and the loader answers the declared name from there before it
looks for anything on disk. That arm works on every platform, needs no
shared engine, and skips both hazards below: the module is this build.
Two hazards shape the engine-locked arm, and both are checked before any Rust symbol is touched:
- Build skew. Nothing detects a layout-changed rebuild naturally: the
dynamic linker resolves happily and
TypeIdequality still passes while field reads are shifted. The only defense is the C-ABI probe (lumen_module_probe_<name>, spelled from the declared name), compared against the engine’s ownlumen_dylib::BUILD_IDfor exact equality. - A second engine instance. If the host process compiled the engine in
(a plain
cargobinary, a static bundle), dlopening a module mapsliblumen_enginea second time; the probe strings would match while worlds and statics differ. The loader asks the running process for the engine’s exportedlumen_engine_build_idsymbol first and refuses every module when it is absent.
The failure policy is banner-and-continue: any load failure prints an unmissable stderr banner naming the module, the reason, and every probed path, and the app keeps booting without that module. One refusal speaks quietly instead: a name that this build neither compiles in nor can open beside a shared engine gets a single stderr line, because that is a property of how the binary was put together, not a defect in the app. A loaded library is never unloaded: the schedules hold function pointers into it for as long as the app lives.
[dependencies]
lumen-audio = { bundled = true }
markdown-widgets = { version = "1.2", tags = ["markdown"] }
shape-tools = { path = "modules/shape-tools", config = { units = "mm" } }The table is unordered, so load order is the sorted key order; declaring order in the file carries no meaning.
tags is how a module introduces markup when nothing installs it ahead
of the parse. A compile reads a web half’s elements from its descriptor
and installs a module with no web half, which registers its own; for any
other module an element the language does not know is refused unless the
app said which module answers for it. See register_declared_tags.
Modules§
- addon
- A module’s web half: the
web/directory of a[dependencies]entry, holding alumen-addon.toml. - language
- Which runtime module runs which script language.
- link_
kit - The link kit: one target’s link line, its inputs, and the modules on it.
Structs§
- DepCfg
- One
[dependencies]entry. - Dependencies
Cfg - The parsed
[dependencies]table: oneDepCfgper declared module, sorted by name, which is the load order. - InitEnv
- What every module in a set is told about the app.
- Loaded
Module - One installed dependency.
- Loaded
Modules - What the loader did, queryable for the life of the app.
- Module
Failure - One dependency that failed to load. The app keeps running without it.
- Portable
Plugins - The portable plugins of one app: the loaded
PluginSets, held for the process lifetime because the app’s script registry points into them. Dropping the resource - the app going down - tells every plugin to shut down, best effort. - Resolved
Modules version-source resolutions handed to the loader by the compiler, keyed by module name.- Target
Cfg - One
[target.<name>]table. - Target
Tables - The
[target]table: what each target adds to the app’s configuration.
Enums§
- Loaded
Kind - Which runtime kind a loaded dependency turned out to be.
- Module
Source - Where one module’s library comes from. A bare string value is shorthand
for
ModuleSource::Version. - Target
- The kind of platform a build is for.
Constants§
- INSTALL_
PREFIX - The prefix of the Rust-ABI install entry, called only after the probe matched exactly.
- PLUGIN_
ENTRY_ SYMBOL - The C-ABI entry a portable plugin exports. One name for every plugin: a portable plugin is opened, never linked in, so two of them never share a symbol table.
- PROBE_
PREFIX - The prefix of the C-ABI probe an engine-locked module exports; the module’s
declared name completes it. The probe returns the module’s NUL-terminated
BUILD_ID, read before any Rust symbol is touched. - REGISTER_
PREFIX - The prefix of the registration entry every module exports, opened or linked. Naming it on a link line is what pulls a module out of an archive that nothing else references.
- RESERVED_
TAGS - The markup tags the language itself owns, which no module may claim.
Functions§
- engine_
dir - The directory of the shared engine library this process runs on, when it
runs on one: where the toolchain keeps its bundled modules, whichever
executable loaded the engine.
Nonefor a process that compiled the engine in, and on Windows, where no engine library exists. - entry_
symbol - One module’s entry symbol: the prefix, then the declared name with every
character a symbol cannot carry replaced by
_. - library_
spellings - The candidate file names of a library called
name, in probe order: the running platform’s spelling first, the other platforms’ after (so one lumen.toml reads the same everywhere), and for a hyphenated name the underscored variant of each (cargo writeslibfoo_bar.sofor a package namedfoo-bar). Every loader that probes for a library by name uses this list: the[[plugins]]path resolution here, the runtime-module probe inlumen-modules, andlumenc package, which stages module libraries into the same names the probes look for. - load_
modules - Load every declared dependency into
app, in sorted-name order, and record the outcome in aLoadedModulesresource. Any failure is a stderr banner plus a failure entry; the app boots without that module. - register_
addon_ elements - Publish the elements the add-ons
addonsanswer for, so the markup parser accepts them. The same registryregister_declared_tagswrites to: a compile does not install a module that has a web half, so the descriptor is what tells the parser the element exists. - register_
declared_ tags - Publish the tags an app’s
[dependencies]table declares, so the markup parser accepts them.