Skip to content
All posts
2 min readtebakopackagingtutorial

Advanced payloads: Runtimes and native code (4 of 5)

The advanced payloads series: runtimes and native code.

The Tebako team

github.com/tamatebako

The basics treated the runtime as the thing that resolves and mounts. This post makes it a choice: which runtime engine, and what happens when your payload contains compiled code. The headline is the reason tebako exists: your users never compile a gem.

Runtimes and native code the runtime is a choice engine: ruby (MRI) the default, ABI-line pinned engine: jruby a JVM runtime, same two artifacts one constraint grammar covers both; the payload declares, tebako resolves native gems, compiled once your gem with C extensions compiled at press, on your CI users never compile anything macos-arm64 macos-x86_64 linux-gnu / musl windows-ucrt one file per triplet — prebuilt, verified, mounted

Figure 1 — Runtime engines are declared, not configured; native gems compile once at press time and ship as prebuilt, verified files per platform.

Runtime engines

The manifest declares the engine; tebako resolves it:

requires:
  - kind: language
    engine: ruby          # or jruby
    constraint: "~> 3.3.0"

An MRI runtime and a JRuby runtime are the same two artifacts — an interpreter executable and an environment image — under the same constraint grammar. A payload with native extensions pins an ABI line (~> 3.3.0) so that a runtime from the wrong line is a named error at startup, never a runtime crash

Native code, compiled once

Gems with C extensions are the classic packaging pain: every user needs a compiler toolchain, matching headers, and luck. Tebako moves the compilation to press time, on your machine or your CI:

$ tebako press -r ./myapp -e bin/myapp -o dist/myapp \
    --target macos-arm64 --target macos-x86_64 \
    --target linux-gnu-x86_64 --target windows-ucrt-x86_64

Each target produces one file with its native gems compiled for that triplet. What your users download is a prebuilt, SHA-256-verified binary — no compiler, no headers, no toolchain. For payloads with no native code at all, one universal file covers every platform.

This is the distribution model in one sentence: the people who build a package compile it; the people who use it never do.

What you can do now

You can choose a runtime engine declaratively, pin ABI lines for native payloads, and ship compiled gems as binaries per platform. The last post shows all of it working at once, on a payload that exercises all of it at once.

Note

Continue with part 5 of 5: packed-mn: one download, any document.