← board

Reduced-compiler build: how is the reduction spelled?

Fork raised by [[feature-a-build-a-reduced-compiler-by-selecting-frontends-and-targets]], which flags only-pascal / only-pascal-and-c / omit-nilpy / only-esp-riscv as deliberate placeholders. Filed rather than guessed: this is the user-facing surface of the feature and it is cheap to decide now, expensive to rename once configurations are documented, tested and shipped.

What the measurement says, because it constrains the answer

Omitting a component is guarding the sites that break when its {$include} goes away (measured by omission on 2026-08-19; full table in the parent ticket):

zig 3 · nilpy 7 · arm32 8 · i386 10 · aarch64 10 · cfront 11 · rust 200 · xtensa 288 · riscv32 518

Two consequences for the spelling:

Options

  1. Subtractive defines only. make PXX_OMIT="c nilpy zig". Honest about the mechanism, composes freely, no translation layer. Cost: the user's own framing was only-pascal, and spelling that means listing eight things to omit and keeping the list correct as frontends are added — a new frontend silently joins every "reduced" build.
  2. Positive list, translated. make PXX_ONLY="pascal esp". Matches how the user talks about it and is future-proof: a new frontend is absent unless named. Cost: a translation table in the Makefile that must know every component, and the awkward case above (only-esp still ships x64 codegen, so the name overpromises).
  3. Named configurations. A small set — full (default), pascal-host, nilpy-esp — each a fixed define set, with no free composition. Cost: no ad-hoc reduction; every new combination is a commit.
  4. Both: subtractive underneath, named configurations as the tested surface.

Recommendation

4. The mechanism is subtractive because the code is; the supported surface is a handful of named configurations, because that is also the only surface Track T can afford to test — the parent ticket's own open question about the matrix answers itself here, as every configuration is a build that can rot silently and the combinatorial set cannot be swept. Free composition stays available and unsupported: PXX_OMIT="..." works, is documented as best-effort, and gates on nothing.

Named set to start, driven by the two motivations on record:

full         (default, byte-identical, the only pinned artifact)
pascal-host  the STRUCTURAL TEST: one frontend, host target, must rebuild the full compiler
nilpy-esp    the PRODUCT: the user's "python compiler for esp at reduced code size"

What is NOT being asked here

What a reduced compiler must still self-host is already ANSWERED by the user (2026-08-19), in the parent ticket: a reduced build must be able to build the FULL compiler from source, which requires the Pascal frontend and the host target. A configuration without the Pascal frontend is not a self-host candidate and is gated on its own frontend's tests instead. No decision needed; recorded here so this ticket is not read as reopening it.

ANSWER (user, 2026-08-21)

"we only need 'omit' — and the makefile can have some sane prefabs"

One mechanism: PXX_OMIT. No positive-list translation layer. The Makefile carries a few prefab targets that expand to an omit list.

So of the four options: 1 as the mechanism, with prefabs playing the role option 4 wanted named configurations to play — but as ordinary Makefile targets spelling out an omit list, not a second surface with its own semantics.

make PXX_OMIT="c nilpy zig"     # free composition, best-effort, gates on nothing
make nilpy-esp                  # a prefab: expands to the omit list above it

The positive list (option 2) is rejected: it buys "a new frontend is absent unless named" at the price of a translation table that must know every component, and a name that overpromises (only-esp still ships x64 codegen, because x86-64 has no ir_codegen_x64.inc — it lives inside the shared ir_codegen.inc). A prefab is a list someone maintains in one visible place, which is the same guarantee without the layer.

State of the mechanism when this was answered

Already 13 components deep and proven — the guards exist and are in use:

PXX_NO_ARM32  PXX_NO_AARCH64  PXX_NO_I386  PXX_NO_CFRONT  PXX_NO_ZIG
PXX_NO_RUST   PXX_NO_ADA      PXX_NO_LOLCODE  PXX_NO_FORTRAN
PXX_NO_ERLANG PXX_NO_BASIC    PXX_NO_ALGOL    PXX_NO_WHITESPACE

What is missing is only the user-facing surface: the Makefile has no PXX_OMIT and no prefab targets. That is the whole of this ticket's implementation.

Note the seven obscure ones (ADA, LOLCODE, FORTRAN, ERLANG, BASIC, ALGOL, WHITESPACE). Nobody composing a minimal build by hand will remember to omit them, which is exactly the job the prefabs do — a prefab that forgets one silently ships it, so a prefab's omit list is the thing to review when a component is added.

Which prefabs are affordable, measured

The guards that exist are the cheap ones. xtensa (288 sites) and riscv32 (518) have none, which inverts the difficulty of the two configurations this ticket proposed:

So ship nilpy-esp first. Name pascal-host if wanted, but as not-yet-buildable rather than a promise backed by guards nobody has written.

[[decide-tobject-root-methods-dispatch-model]] added --compact-classes, which the ESP target turns on by default. That is a codegen flag, not a build-time omission, so it does not belong in PXX_OMIT — but an ESP-facing prefab is the natural place to document that the two travel together.