luna_aot/lib.rs
1#![warn(missing_docs)]
2//! luna-aot — ahead-of-time compiler from Lua source to a
3//! self-contained native binary.
4//!
5//! # Scaffold pipeline (bytecode embed)
6//!
7//!
8//! 1. CLI [`cli::run`] / library [`embed::embed_bytecode`] take a `.lua`
9//! source file.
10//! 2. luna-core's frontend parses + compiles it to bytecode (a
11//! [`luna_core::runtime::Proto`] tree).
12//! 3. The bytecode is dumped via [`luna_core::vm::dump`] (luna's own
13//! body format — `"\x1bLua" + version-byte` header + the
14//! `"\x00LunaV1\x00"` sentinel + luna body).
15//! 4. The dump bytes are written into a `.luna.bytecode` section of an
16//! ELF / Mach-O / PE object file via [`object::write::Object`],
17//! bracketed by two **public** symbols
18//! `__luna_bytecode_start` and `__luna_bytecode_end` that the
19//! runtime stub (or a custom host binary) `extern "C"`s.
20//! 5. The CLI invokes system `cc` to link the bytecode object + a
21//! minimal C entry point into a final executable. The default
22//! scaffold entry just prints the embedded bytecode length to
23//! `stderr` and exits — proving the section is reachable end-to-end.
24//!
25//! # Why a separate crate
26//!
27//! This crate pulls `object` + `clap` and all of cranelift;
28//! embedders who only want the runtime JIT keep using `luna-jit`, and
29//! embedders who only want pure interp keep using `luna-core` — both stay free of `luna-aot`'s build-time
30//! dep tree.
31//!
32//! **`luna-core` 0-third-party-dep contract is unaffected.** This
33//! crate depends on `luna-core` but `luna-core` does not depend on
34//! anything here. The CI gate
35//! (`cargo tree -p luna-core --prefix none | grep -cE " v[0-9]"`)
36//! continues to report `1`.
37
38/// Symbol name marking the start of the embedded bytecode section.
39/// External (C-ABI) symbol; the runtime stub declares it as
40/// `extern "C" { static __luna_bytecode_start: u8; }`.
41pub const BYTECODE_START_SYMBOL: &str = "__luna_bytecode_start";
42
43/// Symbol name marking the end of the embedded bytecode section.
44/// External (C-ABI) symbol; the runtime stub declares it as
45/// `extern "C" { static __luna_bytecode_end: u8; }` and computes the
46/// length as `(&end as *const u8).offset_from(&start as *const u8)`.
47pub const BYTECODE_END_SYMBOL: &str = "__luna_bytecode_end";
48
49/// Object-file section name for the embedded bytecode.
50/// ELF/Mach-O conventions: a leading dot is the standard for non-loader-
51/// special sections; we pick `.luna.bytecode` so `objdump -s -j
52/// .luna.bytecode <out>` displays the dump bytes for inspection.
53pub const BYTECODE_SECTION_NAME: &str = ".luna.bytecode";
54
55pub mod cli;
56pub mod embed;
57// `runtime_stub` declares `extern "C" { static __luna_bytecode_start: u8 }`
58// + `__luna_bytecode_end`. These symbols are linker-provided by the
59// bytecode `.o` that `embed::embed_bytecode` writes; they exist only in
60// the AOT-produced binary's link set, not in the luna-aot crate's own
61// builds (rlib / test / doctest).
62//
63// Most linkers (ld / lld / Mach-O) tolerate unresolved `extern`
64// references unless something actually calls them. MSVC's `link.exe`
65// is stricter — even unused references trigger LNK2019. So the module
66// is gated off when building the luna-aot crate itself under MSVC;
67// the user-side Cargo bootstrap recipe (see `runtime_stub::aot_main`
68// rustdoc § Wiring) re-enables it by setting
69// `RUSTFLAGS=--cfg luna_aot_runtime_stub` when compiling against the
70// real bytecode object link set. Tier-1 deploys via the AOT pipeline's
71// own `cc` invocation (`embed::compile_and_link`) use the C entry +
72// `luna_aot_run` from `luna-runtime-helpers`, not this Rust stub.
73#[cfg(any(not(target_env = "msvc"), luna_aot_runtime_stub))]
74pub mod runtime_stub;