moxzi
Docs / Getting started / Your first compile

Your first compilealpha

How do I turn a .mo file into an installable wasm and see what happened?

A moxzi build is one command that reads a .mo entry file and writes two artifacts next to it: a linked, deployable .wasm and the .did candid interface that describes it. The constraint to know before you start is that an actor must say persistent; a bare actor { … } is rejected, on purpose, because that is how a program declares its state survives an upgrade.

Compile it#

cat > hello.mo <<'EOF'
persistent actor {
  var count : Nat = 0;
  public func inc() : async Nat { count += 1; count };
  public query func greet(name : Text) : async Text { "Hello, " # name # "!" };
};
EOF
moxzi build hello.mo -o hello.wasm
hello.mo -> hello.wasm + hello.did (223251 bytes, 1 file(s), 58 steps, 0.67s)
compiled by /…/compiler.wasm (sha256 7beb08e90ecf6ff21b7a0c92206c01edcc623a7566142b94cad96e31cdceca62), moxzi 0.1.0-alpha.1

Reading the two lines#

FieldMeaning
hello.wasm + hello.didboth artifacts were written; --no-idl suppresses the .did
223251 bytessize of the linked module — the deployable one
1 file(s)how many source files were in the upload closure (see moxzi deps)
58 stepsdriver messages the compiler ran; on-chain this is roughly the round count
0.67swall clock, including loading the compiler from the AOT cache
compiled by … (sha256 …)provenance: which compiler wasm produced these bytes
moxzi 0.1.0-alpha.1the host CLI version

The provenance line is printed, never embedded in the artifact. Embedding it would have to be byte-identical between a local build and an on-chain one for the byte-parity claim to survive, so it stays outside the wasm. When two builds disagree, compare those hashes first: the same compiler hash and the same sources produce the same bytes.

The .did is the candid interface the runtime and any agent needs:

service : {
  greet: (name: text) -> (text) query;
  inc: () -> (nat);
}

Seeing the phases#

--timings splits the wall clock and adds the compiler's own memory numbers:

moxzi build hello.mo -o hello.wasm --timings
rts: allocated 0.07 GB, reclaimed 0.06 GB, peak live 5 MB, heap 13 MB, committed 201 MB
on-chain estimate: ~79 rounds (~0.02 h at 1s/round, ~0.01 h at 0.4s) | dirty-budget floor 1 rounds
timings: module 0.033s (cached), sources 0.001s, instantiate 0.001s, compile 0.208s, link 0.358s (66825 -> 223251 bytes)

Two things worth noticing. module 0.033s (cached) is the ahead-of-time cache doing its job — the first run on a new machine says (JIT) and costs about a second, because the compiler is a 7.8 MB memory64 module that wasmtime has to compile before it can run your code. And 66825 -> 223251 bytes is the link step: the compiler emits a small unlinked module, and linking adds the runtime system that makes it a canister.

The on-chain estimate is a projection from local step count, not a measurement of your program on the IC. Treat it as an order of magnitude.

Seeing what was compiled#

moxzi deps prints the upload closure — every file a build touches, and the virtual path it is compiled under:

moxzi deps hello.mo
root  : /…/demo
pkgs  : none (no mops.toml)
entry : /src/hello.mo
files : 1 (180 bytes)

      180  /src/hello.mo
           <- /…/demo/hello.mo

Those /src/… names are not cosmetic. The compiler records source paths in what it emits, so the same file compiled as /src/hello.mo and as /ext/hello.mo produces different bytes. Machine-independent VFS naming is what lets your build and someone else's agree.

Deploying what you built#

hello.wasm is a real canister module. It installs on the Internet Computer with the IC SDK (dfx canister install <canister> --wasm hello.wasm), runs under moxzid, and runs in a browser tab under moxzi-web — the same bytes in all three places.

When it fails#

Errors are source-located and carry moc's codes, so editor tooling and habits carry over:

Error: compilation failed:
/src/hello.mo:1.0-1.5: type error [M0220], this actor or actor class should be declared `persistent`

Two failure modes surprise people the first time:

SymptomWhat it means
[M0220] … should be declared 'persistent'you wrote a bare actor; add persistent, or pass --default-persistent-actors to have it rewritten
a successful build printing no warnings at allexpected — moxzi build surfaces diagnostics only when the compile fails; it does not report warnings on success

Things you cannot do#

Next#

On this pageCompile itReading the two linesSeeing the phasesSeeing what was compiledDeploying what you builtWhen it failsThings you cannot doNext