12.3. Runtime bootstrap
Before any program can be compiled, an installation needs a compiler and a runtime built for the machine it runs on. The compiler is distributed as a prebuilt binary in a release; the runtime is built from source on the target bymorloc init, against the toolchain the environment provides. This section specifies what a release contains, howmimverifies and installs it, whatmorloc initproduces, and when it rebuilds.
12.3.1. Releases
A release is named by a tag. latest means the newest release, and a bare
version such as 0.105.2 means tag v0.105.2. Each release publishes a
release manifest, a JSON object:
| Field | Meaning |
|---|---|
|
The manifest’s own format version. A reader refuses a schema newer than it knows. |
|
The Morloc version the release contains. |
|
Per platform ( |
|
The name of the archive holding the runtime’s source. |
|
The SHA-256 digest of every asset. |
|
The contract versions of this release: |
mim reads the manifest before downloading anything else and refuses a
release whose contract versions it cannot read, telling the user to upgrade
mim. A platform the manifest does not list is refused with a pointer to a
container backend, since a container runs the Linux build on any host.
Every asset is downloaded to a temporary name, checked against its digest, and only then renamed into place. A missing digest is a refusal, not a warning. A downloaded release is stored once per scope, keyed by version and platform, and marked complete only after all of its assets are in place; an incomplete one is never used.
12.3.2. Building an environment
For a container backend, mim first builds an image for the environment
from a base Linux image, the system packages the user asked for, any extra
certificate authorities, the compiler, the runtime source, and its own
binary. It is rebuilt only when one of these inputs changes. The solved
toolchain and the built runtime are not in the image: they live in the
environment’s data and are mounted in, so a package change does not rebuild
the image.
Then, for every backend, mim solves the toolchain the compiler requires
(Environment solving) and runs morloc init inside the environment, in a strict
mode in which every compiler and interpreter must come from the solved
toolchain rather than the host.
An environment can carry a bundle of extra certificate authorities, for networks that inspect TLS. The bundle is checked to contain certificates only (a private key is refused), installed as a trusted root in the image, and passed to the solver and every package manager in the environment.
12.3.3. What morloc init produces
morloc init builds the runtime into the Morloc home:
| Output | Purpose |
|---|---|
|
The runtime’s C API (Runtime library API). |
|
The shared library every pool links against. |
|
The nexus. |
Per-language bindings |
One for each supported language whose tools are present: a Python extension module, an R library, a C++ library and precompiled header, a prebuilt Rust crate. |
|
A copy of the runtime source, used when compiling Rust pools. |
The runtime source is found, in order, at a path named by
MORLOC_RUST_DIR, in the home’s rust/ directory, or beside the compiler
binary. Building it requires a Rust toolchain. The runtime is always built
optimized; a sanitizer variant exists for debugging the runtime itself.
A language whose tools are missing is skipped with a warning, and its
programs cannot be built until a later init succeeds. In strict mode a
missing or foreign tool is an error instead, so an environment never
silently falls back to the host’s compiler.
Only one init runs per home at a time; a second waits for the first.
init rebuilds the runtime and every language binding unless it is run in
incremental mode, which keeps each part that is already present. -f also
removes the files init owns before rebuilding, so a binding left by an
older version cannot survive.
init links morloc-nexus into a directory on the user’s PATH (by
default ~/.local/bin when it exists; MORLOC_BIN_LINK_DIR names another,
and an empty value turns linking off). mim turns it off inside
environments so that no environment changes the user’s global commands.
Interpreter pinning. The Python and R bindings are compiled against one minor version of their interpreter. Once an environment has built them, the interpreter’s minor version is pinned in every later solve of that environment (Environment solving), and a binding that no longer matches its interpreter is rebuilt before the next build uses it.