feat(compiler): #75 resolve the auto-spliced engine runtime from LUDIC_HOME
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 23s
ci / build-and-test (push) Successful in 2m25s
commit-lint / conventional-commits (push) Successful in 6s
docs / build-and-deploy (push) Successful in 28s

The compiler auto-splices runtime/native/* for any ECS game, but resolved it
relative to the build CWD, then fell back to the package module root
($LUDIC_MODULES) — forcing every external project to copy/symlink the engine
runtime into ludic_modules/. The runtime is part of the toolchain, not the
project: do_import now resolves a runtime/... import that isn't found locally
from $LUDIC_HOME (default: the compiler binary's dir — where cocoa.ll/audio.ll
already come from), before the module root. So ludic_modules/ holds only
third-party packages.

In-repo builds are byte-identical (the runtime resolves locally there, so the
$LUDIC_HOME fallback never fires; fixpoint holds). Verified by a hermetic test
that builds an ECS game from an external CWD with no runtime/ or ludic_modules/
under it, resolving the runtime from LUDIC_HOME. Full suite 113/0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-02 07:49:10 +03:00
parent ad3be0c53c
commit ab4546e365
5 changed files with 17240 additions and 17005 deletions

View file

@ -94,7 +94,16 @@ The compiler resolves an import first relative to the importing file, then — f
a non-absolute path that is not found — under the package module root
(`$LUDIC_MODULES`, default `ludic_modules/`). So a fetched package's code is
spliced into the build and its namespace becomes available exactly the way the
built-in stdlib namespaces (Regex.\*, Grid.\*, …) are. Because Ludic compiles
built-in stdlib namespaces (Regex.\*, Grid.\*, …) are.
The **engine runtime is the exception** (issue #75): the compiler auto-splices
`runtime/native/*` for any ECS game, and that runtime ships with the *toolchain*,
not the project. A `runtime/...` import that is not found relative to the build is
resolved from the install root **`$LUDIC_HOME`** (default: the compiler binary's
directory — the same place the platform `.ll` files come from), *before* the
package module root. So an external game does not have to copy or symlink the
engine runtime into its `ludic_modules/`; that directory holds only third-party
packages. In-repo builds are unaffected — the runtime resolves locally there. Because Ludic compiles
ahead-of-time, a source package is compiled *into* the consumer's binary — no
ABI seam, and the whole-program guarantees (determinism, replay, `world_save`)
still hold.