Class: Lilac::CLI::BytecodeBuilder
- Inherits:
-
Object
- Object
- Lilac::CLI::BytecodeBuilder
- Defined in:
- lib/lilac/cli/build/bytecode_builder.rb
Overview
Compiles aggregated Ruby source to mruby bytecode, then writes it under the build output with a content-hash filename so browsers cache-invalidate automatically when the bytes change.
Used by Builder when target == :compiled. Owns the compile
subprocess (or wasm driver) lifecycle and error translation;
Builder keeps the HTML / vendor concerns.
Backend dispatch — first hit wins:
1. explicit `mrbc_path:` (from `Lilac::CLI.configure { c.mrbc_path = ... }`
or `--mrbc-path` CLI flag) → :binary
2. ENV["MRBC"] → :binary
3. ENV["MRUBY_WASM_RUNTIME_PATH"]/mruby/build/host/bin/mrbc → :binary
4. `lilac-wasm-bin` gem ships `mrbc-host.wasm` AND wasmtime-rb
loadable AND module instantiates with required exports → :wasm
5. `mrbc` on $PATH → :binary
The wasm-driven backend is the "default for end users" path — a
scaffolded lilac new Gemfile pulls in lilac-wasm-bin and
wasmtime, so gem install lilac-cli && bundle install is enough
to make lilac build --target compiled work without any external
binary. Explicit mrbc_path / ENV vars override (priority 1-3) so
devs who built mruby themselves get the native path.
If nothing resolves, raises BuildError pointing at the most likely fix paths.
Defined Under Namespace
Classes: Error
Constant Summary collapse
- HASH_LENGTH =
8 hex chars (32 bits) — enough collision resistance for cache busting, short enough to keep filenames readable.
8
Instance Method Summary collapse
-
#build(ruby_source, source_label: '(aggregated)') ⇒ Object
Compile a Ruby source string into a
.mrbfile underoutput_dir. -
#compile_to_bytes(ruby_source, source_label: '(aggregated)') ⇒ Object
Compile a Ruby source string into raw mruby bytecode (no write, no hashing).
-
#initialize(output_dir: nil, mrbc_path: nil, basename: 'app', disable_gem_discovery: false) ⇒ BytecodeBuilder
constructor
A new instance of BytecodeBuilder.
-
#resolve_backend ⇒ Object
Diagnostic accessor: returns
[:binary, "/path"]or[:wasm, "/path/to/wasm"]describing which backendbuildwould select, or nil when nothing resolves. -
#resolve_mrbc ⇒ Object
Resolved mrbc binary path for
lilac doctorand back-compat.
Constructor Details
#initialize(output_dir: nil, mrbc_path: nil, basename: 'app', disable_gem_discovery: false) ⇒ BytecodeBuilder
Returns a new instance of BytecodeBuilder.
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/lilac/cli/build/bytecode_builder.rb', line 47 def initialize(output_dir: nil, mrbc_path: nil, basename: 'app', disable_gem_discovery: false) @configured_mrbc_path = mrbc_path @output_dir = output_dir @basename = basename # Mirrors `CompiledRuntimeResolver`'s kwarg — lets the bytecode # builder's tests sandbox out the gem's `mrbc-host.wasm` when # they want to assert specific discovery fallbacks. Production # callers leave it false and the gem's wasm is picked up by # default (priority #4). @disable_gem_discovery = disable_gem_discovery end |
Instance Method Details
#build(ruby_source, source_label: '(aggregated)') ⇒ Object
Compile a Ruby source string into a .mrb file under
output_dir. Returns the basename of the produced file (e.g.
"app.a3f29b21.mrb") so the caller can wire it into a fetch URL.
63 64 65 66 67 68 69 70 71 |
# File 'lib/lilac/cli/build/bytecode_builder.rb', line 63 def build(ruby_source, source_label: '(aggregated)') raise Error, '`build` requires `output_dir:` at construction time' unless @output_dir FileUtils.mkdir_p(@output_dir) bytecode = compile_to_bytes(ruby_source, source_label: source_label) filename = "#{@basename}.#{content_hash(bytecode)}.mrb" dest = File.join(@output_dir, filename) File.binwrite(dest, bytecode) filename end |
#compile_to_bytes(ruby_source, source_label: '(aggregated)') ⇒ Object
Compile a Ruby source string into raw mruby bytecode (no write,
no hashing). Used by lilac package-build which wants explicit
control over output path / filename — it has no need for the
content-hash cache-busting that build does for .lil apps.
77 78 79 80 81 82 83 |
# File 'lib/lilac/cli/build/bytecode_builder.rb', line 77 def compile_to_bytes(ruby_source, source_label: '(aggregated)') backend = resolve_backend! case backend.first when :binary then compile_via_binary(backend.last, ruby_source, source_label) when :wasm then compile_via_wasm(backend.last, ruby_source, source_label) end end |
#resolve_backend ⇒ Object
Diagnostic accessor: returns [:binary, "/path"] or
[:wasm, "/path/to/wasm"] describing which backend build would
select, or nil when nothing resolves. Doesn't raise — lilac doctor uses it to render the OK / WARN line; build calls
resolve_backend! instead.
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/lilac/cli/build/bytecode_builder.rb', line 90 def resolve_backend if (binary = resolve_mrbc_binary) return [:binary, binary] end if (wasm = discoverable_mrbc_host_wasm) && WasmMrbcDriver.available?(wasm_path: wasm) return [:wasm, wasm] end if (path_binary = path_lookup('mrbc')) return [:binary, path_binary] end nil end |
#resolve_mrbc ⇒ Object
Resolved mrbc binary path for lilac doctor and back-compat.
Nil when no binary is discoverable (gem-provided wasm doesn't
count). Renamed-but-kept-as-alias for callers that pre-date the
backend dispatch (e.g. existing tests).
108 109 110 |
# File 'lib/lilac/cli/build/bytecode_builder.rb', line 108 def resolve_mrbc resolve_mrbc_binary || path_lookup('mrbc') end |