moxzi
Docs / CLI / Coming from moc

Coming from mocalpha

Which moc flags map to moxzi, and which deliberately differ?

moxzi aims to be a drop-in replacement for moc on the common path: compile a Motoko entry file into a deployable canister module, with the same diagnostics and the same package flag. The constraint is that it is a different compiler implementation of the same language, so the surface it exposes is narrower on purpose — there is no interpreter, no REPL, and no warning-control machinery.

The flags below were checked against moxzi build --help from the CLI's clap definitions (moxzi/src/main.rs) and against moc --help from moc 1.14.1, the version the compiler is ported to — the string a moxzi-built canister carries in its motoko:compiler metadata is 1.14.1, and it earns that claim by measurement: zero unported upstream language tests, a 384-of-384 module sweep over the top 40 mops packages, and a byte-identical self-compile.

The command itself#

moc -c --idl -o main.wasm --package base .mops/base@0.16.0/src src/Main.mo
moxzi build src/Main.mo -o main.wasm --package base .mops/base@0.16.0/src

The differences visible in that one line: the entry file is a positional argument to a build subcommand rather than a trailing operand, -c is implied, and --idl is implied (moxzi always writes the .did unless told not to).

Direct equivalents#

mocmoxziNotes
-cmoxzi buildcompiling is what build means
-o <file>-o, --out <WASM>defaults to the entry name with .wasm
--package <name> <path>--package <NAME> <PATH>identical semantics, repeatable
--idlon by default--no-idl turns it off
-no-link--no-linknote moc's single dash
--stable-regions--stable-regions
--max-stable-pages <n>--max-stable-pages <N>0 means the canister default (65536)
--stabilization-instruction-limit <n>--stabilization-instruction-limit <N>0 means the canister default
-measure-rts-stack--measure-rts-stacknote moc's single dash
--trap-on-call-error--trap-on-call-error
--print-depsmoxzi depsdifferent output: moxzi prints the whole closure with VFS paths, not one file's direct imports
--enhanced-migration <dir>--enhanced-migration <DIR>the migration-chain system; see Migrations
--stable-baseline <file.most>--stable-baseline <MOST>the deployed signature the chain is checked against. One deliberate improvement: moxzi carries upstream's post-1.14.1 fix (#6318), so the check resumes at the migration the baseline records as already applied instead of replaying the whole chain — 1.14.1 itself wrongly errors after a field-dropping migration
--stable-compatible <pre> <post>moxzi stable-compatible <pre> <post>a subcommand rather than a flag; same M0169/M0170/M0216 verdicts
--public-metadata <name>, --omit-metadata <name>same namesone difference of DEFAULT: raw moc is all-private, moxzi's default is dfx's (candid:service and candid:args public). Passing --public-metadata replaces that default, as it does in moc
--default-persistent-actors--default-persistent-actorsverified equivalent: both rewrite a bare actor to persistent actor

Deliberate differences#

AreamocmoxziWhy
Non-persistent actorsrejects with M0220 by default; --legacy-actors opts outrejects with M0220; --legacy-actors is retiredthe two agree on the default. moxzi drops the legacy escape hatch entirely: silently compiling an actor that does not declare its state survives is the mistake worth failing on. --default-persistent-actors rewrites bare actors on both
Candid emission--idl, off by defaultalways on, --no-idl to suppressa canister without its interface file is not deliverable
Metadata visibilityraw default is all-privatecandid:service and candid:args are publicfollows dfx, not raw moc, so a deployed canister's interface is readable without controller rights
Backend--legacy-persistence still selectableenhanced orthogonal persistence only--no-eop is retired: the classical backend's IR is never closed and traps in ConstFold on any program
Warningsprinted, and controllable (-A/-W/-E)printed, not controllablea successful build prints the warnings the compiler emits (float precision M0266, migration-chain M0254, and others), but there is no per-code leveling machinery. Coverage is also narrower than moc's — see Language support status
GC selection--incremental-gc, --copying-gc, …noneincremental GC with EOP is the only configuration
--force-gcforces GC in the generated code, for testingforces the compiler's own collector to run at each message boundarysame name, different subject: moxzi's is a host-side knob and does not change the artifact

Verified behavioural difference: --debug#

moc's --debug is the default and keeps debug { … } expressions; --release strips them. In moxzi, --debug currently makes no observable difference:

moxzi build dbg.mo -o dbg-rel.wasm
moxzi build dbg.mo -o dbg-dbg.wasm --debug
cmp dbg-rel.wasm dbg-dbg.wasm     # identical

For the same source, moc's --release output contains no trace of the debug string while its --debug output does; both moxzi outputs contain it. In other words moxzi behaves like moc's default, and there is no --release equivalent that strips debug expressions. If you rely on --release stripping, do not assume it here.

Flags with no moxzi equivalent#

mocStatus in moxzi
-r, -i, -iR, -t (interpret, REPL, trace)absent — moxzi only compiles
--check (type-check only)absent
--stable-types (separate .most emission)absent as a flag — the signature is always embedded in the module's motoko:stable-types section, which is what --stable-compatible/upgrades read
-A, -W, -E, -Werror, --hide-warnings, --warn-helpabsent — warnings print but there is no leveling machinery
--error-format, --error-detail, --error-recovery, --ai-errors, --explainabsent — diagnostics come out in moc's plain file:line.col-line.col: kind [Mxxxx], message form only
--actor-idl, --actor-alias, --actor-id-alias, --actor-env-aliasabsent
-g, --map (debug info, source maps)absent
--profile*, --sanity-checks, -dp, -dt, -dlabsent
--args <file>, --args0 <file>absent
-fshared-code / -fno-shared-codeabsent
--experimental-*, --rts-stack-pagesabsent

moxzi flags moc has no analogue for#

FlagWhat it is for
--stack-budget <N>how often the compiler's own scheduler yields — a cost knob, not an output knob
--root <DIR>what /src maps to in the virtual filesystem
--compiler / --linker, MOXZI_COMPILER / MOXZI_LINKERwhich compiler and linker wasm to run
--remote <URL> --canister <ID>run the compile on a compiler canister instead of locally
--progress <N>, --status-secs <S>, --max-steps <N>observe and bound a long build
--timingsper-phase timing plus the compiler's memory numbers

The environment variables moxzi reads are MOXZI_COMPILER, MOXZI_LINKER, MOXZI_MOPS, MOXZI_IDENTITY, MOXZI_WASM_STACK, MOXZI_NATIVE_STACK, MOXZI_MEM_RESERVE, MOXZI_FUEL and MOXZI_PARSE_WINDOW.

Unverified / to confirm#

These could not be checked against a running binary in this repo and should be treated as open questions rather than documented behaviour:

Next#

On this pageThe command itselfDirect equivalentsDeliberate differencesVerified behavioural difference: --debugFlags with no moxzi equivalentmoxzi flags moc has no analogue forUnverified / to confirmNext