Skip to main content

Compile

Beginner
Tutorial

Overview

After you have written the code for your project's canisters and created them, you need to compile the code into a WebAssembly module before it can be deployed on ICP.

You must create your canisters before you can build them; otherwise, you will receive an error message saying they do not exist.

dfx build looks for source code to compile for each canister configured under the canisters section in the dfx.json file. It can be used to compile a specific canister or all canisters defined in the project.

Verify the location of your project's files and their file names. If necessary, edit your project's dfx.json file to reflect the current intended configuration.

Compiling your canister

To compile your canister's Wasm module, you can use the dfx build command.

Compile your canisters from within the project's directory:

  • dfx build <canister-name>: Compile a canister locally. The local replica must be running to compile a canister locally. Start it with dfx start --background.

  • dfx build <canister-name> --network=playground: Compile a canister on the playground. Compiling a canister on the playground is free, but canisters are temporary and will be removed after 20 minutes.

  • dfx build <canister-name> --network=ic: Compile a canister on the mainnet. Compiling a canister on the mainnet will cost cycles.

  • dfx build --network=ic: Compile all canisters in the project's dfx.json file on the mainnet.

Compilation happens on the local machine of the developer.

dfx build isn't the only workflow that can be used for compiling code. For example, Rust canisters can be compiled using cargo.

When this command is executed, the following steps happen:

  • The source code for a canister is compiled into a Wasm module.

  • If a canister is written in Motoko, type declarations are automatically generated using Candid.

  • If a canister is written in Rust, the build process checks for Rust vulnerabilities.

How code is compiled to Wasm

WebAssembly (Wasm) is a platform-independent binary format that can be executed in the Wasm virtual machine. Many modern compilers support Wasm as the compilation target along with traditional targets such as x86 and arm32.

There are three types of Wasm depending on where the Wasm virtual machine is hosted and how it interacts with users and the host environment:

  • Web browser: The Wasm program interacts with the users via the JavaScript bindings of the browser. The primary toolchain for compiling Wasm for browsers is Emscripten. Note that such Wasm programs are incompatible with ICP.

  • WASI: This abbreviation stands for WebAssembly System Interface. It is becoming the standard for running Wasm programs outside of Web browsers. Major Wasm runtimes such as Wasmtime and Wasmer support this standard. Compilers denote this target as wasm32-wasi. ICP does not directly support WASI, but it is possible to preprocess a WASI program and make it runnable on ICP with the community project wasi2ic.

  • Vanilla Wasm: There is no standard API for interacting with users and the host environment. Every host environment provides its own API. ICP uses this approach and provides a set of functions, called the System API, to the Wasm program. Many compilers denote this target as wasm32-unknown-unknown since they do not know the target host environment and do not make any assumptions about the available APIs.

The Canister Development Kit (CDK) of supported programming language comes with build scripts that link the System API and compile the code to Wasm programs that are compatible with ICP:

  • Rust and Motoko compile to the wasm32-unknown-unknown target directly under the hood.
  • Azle and Kybra first compile to the wasm32-wasi target and then convert the Wasm binary to wasm32-unknown-unknown using the wasi2ic tool.

For convenience of developers, dfx wraps the CDK specific build scripts and provides the dfx build command to compile the code to a Wasm binary.