Compile
Overview
After you have written the code for your project's canisters, you need to compile the code into a WebAssembly module before it can be deployed on ICP.
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 the 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 projectwasi2ic
.Vanilla Wasm: there is no standard API for interacting with users and the host environment. Every host environment provides their own API. ICP uses this approach and provides the 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 towasm32-unknown-unknown
using thewasi2ic
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.
Compiling your canister
To compile your canister's Wasm module, you can use the dfx build
command.
dfx
isn't the only workflow that can be used for compiling code. For example, Rust canisters can be compiled using cargo
.
The dfx build
command looks for source code to compile for each canister configured under the canisters
section in the dfx.json
configuration file. It can be used to compile a specific canister or all canisters defined in the project's dfx.json
file.
Check out the default project template for more information on dfx.json
.
Before using the dfx build
command, first you need to create the canister and verify the location of your project's files and their file names. If you modify these settings, be sure to edit your project's dfx.json
file to reflect the current intended configuration.
Then, compile your canister code with the command:
dfx build
Compilation happens on the local machine of the developer. Compiled Wasm binary is then installed on the target canister, which costs cycles.
This command must be run from within the project's directory.
When this command is executed, the following steps happen:
The source code for each canister defined in
dfx.json
is compiled into a Wasm module.If a canister being built is written in Motoko, type declarations are automatically generated using Candid.
If a canister being built is written in Rust, the build process checks for Rust vulnerabilities.
When a canister is deployed with dfx deploy
, the dfx build
command is run in the background as part of the deployment process.
Once your canister has been compiled, it is ready to be deployed.