moxzi
Docs / CLI / Building with moxzi

Building with moxzialpha

Compile Motoko to a deployable wasm module, control warnings and output, and see where build time goes.

moxzi build compiles a Motoko entry file and writes a wasm module you can deploy, plus its Candid interface. This page covers the options you'll use day to day. Every flag is listed in the CLI reference.

Build a module#

hello.mo
actor {
  public query func greet(name : Text) : async Text {
    "Hello, " # name # "!"
  };
};
mkdir -p out
moxzi build hello.mo -o out/hello.wasm
ls out
hello.mo -> out/hello.wasm + out/hello.did (243956 bytes, 1 file(s), 50 steps, 0.51s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9
hello.did
hello.wasm
Part of the outputMeaning
out/hello.wasm + out/hello.didThe files written. Without -o, they go next to the entry file
247440 bytesSize of the deployable module
1 file(s)Source files in the build, including package files
58 stepsCompiler work units. Larger projects take more
compiled by … (sha256 …)The compiler that produced this module. The same compiler and the same sources always produce the same bytes

The output directory must already exist.

The module is ready to deploy. Install it on the Internet Computer with dfx or icp, host it with moxzid, or load it with moxzi-web.

Every actor is persistent: its variables keep their values across upgrades. Writing persistent actor still compiles, with warning M0217 that the keyword is redundant.

Warnings#

Warnings print before the summary line and don't stop the build:

shop.mo
actor {
  var orders : Nat = 0;

  public func order(quantity : Nat) : async Nat {
    let unused = quantity * 2;
    orders += quantity;
    orders
  };
};
moxzi build shop.mo
/src/shop.mo:5.9-5.15: warning [M0194], unused identifier: `unused`
shop.mo -> shop.wasm + shop.did (244475 bytes, 1 file(s), 50 steps, 0.51s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9

Turn a warning into an error with -E, or silence it with -A:

moxzi build shop.mo -E M0194 || echo "exit code $?"
Error: compilation failed:
/src/shop.mo:5.9-5.15: type error [M0194], unused identifier: `unused`
exit code 1
moxzi build shop.mo -A M0194
shop.mo -> shop.wasm + shop.did (244475 bytes, 1 file(s), 50 steps, 0.56s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9

-W CODE enables a warning that's off by default. All three options repeat, and they're applied in command-line order. They work the same way as in moc.

Common options#

OptionEffect
-o, --out FILEWhere to write the wasm. The .did goes beside it
--no-idlDon't write the .did file
--gzipAlso write FILE.gz. The IC accepts gzipped modules, and you need one to pass a large module as a call argument
--debugKeep debug { … } blocks. moxzi builds release by default; moc builds debug by default
--package NAME PATHMake mo:NAME/… imports resolve to PATH. Repeatable. See Projects and packages
--root DIRThe project directory, which the compiler sees as /src. Defaults to the nearest directory with a mops.toml or dfx.json, else the entry file's directory
--stable-typesAlso write the stable signature as a .most file, used to check upgrades
--compact-rtsLink a runtime that keeps the heap smaller. For moxzid and moxzi-web only; not for the IC

--gzip with --no-idl:

moxzi build hello.mo --gzip --no-idl
ls hello.wasm*
hello.mo -> hello.wasm + hello.wasm.gz (243956 bytes, 1 file(s), 50 steps, 0.60s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9
hello.wasm
hello.wasm.gz

Large projects#

On a project with hundreds of files, raise the compiler's scheduling budget with --stack-budget. It changes how often the compiler pauses between work units, not what it produces. On a large project it can cut a build from hours to minutes:

moxzi build hello.mo --stack-budget 20000

To watch a long build, add --progress 500 to print a line every 500 steps, or --status-secs 10 to also print the current compiler phase, at most every ten seconds.

Build time#

--timings breaks down where the time went:

moxzi build hello.mo --timings
hello.mo -> hello.wasm + hello.did (243956 bytes, 1 file(s), 50 steps, 0.53s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9
rts: allocated 0.07 GB, reclaimed 0.06 GB, peak live 5 MB, heap 11 MB, committed 201 MB
on-chain estimate: ~68 rounds (~0.02 h at 1s/round, ~0.01 h at 0.4s) | dirty-budget floor 1 rounds
timings: module 0.037s (cached), sources 0.001s, instantiate 0.002s, compile 0.140s, link 0.329s (55322 -> 243956 bytes)
PhaseWhat it is
moduleLoading the compiler. (cached) means it was already prepared for your CPU; the first build after an install or upgrade says (JIT) and takes about a second longer
sourcesReading source files
compileCompiling
linkAdding the Motoko runtime to the compiled code

For a small program, linking takes longer than compiling. Link time is roughly fixed; compile time grows with your program.

moxzi cache path shows where prepared compilers are cached, and moxzi cache clear empties the cache.

Compiling and linking separately#

moxzi build compiles your code and then links it with the Motoko runtime. --no-link stops after compiling, and moxzi link does the second half:

moxzi build hello.mo --no-link -o unlinked.wasm
moxzi link unlinked.wasm -o hello.wasm
hello.mo -> unlinked.wasm + unlinked.did (55322 bytes, 1 file(s), 50 steps, 0.19s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 fbfb83d4ee2a40739c33c20dff3a3fc98c56b92eb5c76eed624c8efe298bc463), moxzi 0.1.0-alpha.9
unlinked.wasm -> hello.wasm (55322 -> 243956 bytes, 0.33s)

An unlinked module can't be deployed and fails wasm validation. The on-chain builder produces unlinked modules; moxzi build --remote links them for you, so you only need moxzi link when you fetch one yourself.

Listing the files in a build#

moxzi deps shows every file the build would read and the path the compiler sees it at:

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

       97  /src/hello.mo
           <- ./hello.mo

The compiler sees your project's files under /src and packages under /pkg/NAME. Paths in error messages use these names, which keeps builds identical across machines.

Limitations#

LimitationWhat to do
One entry file per moxzi buildRun it once per canister
No type-check-only modeRun a build and discard the output
No interpreter or REPL (moc -r, moc -i)Use moxzid to run the actor

Next steps#

On this pageBuild a moduleWarningsCommon optionsLarge projectsBuild timeCompiling and linking separatelyListing the files in a buildLimitationsNext steps