Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 67 additions & 36 deletions recipes/motoko/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Motoko Recipe

Compile Motoko source code using the moc compiler to create IC canisters.
Compile Motoko source code using `mops build` to create IC canisters.

## Usage

Expand All @@ -12,26 +12,34 @@ canisters:
recipe:
type: "@dfinity/motoko@<version>"
configuration:
main: src/main.mo
shrink: true
```

> Replace `<version>` with a release version (e.g. `v4.0.0`). See [available versions](https://github.com/dfinity/icp-cli-recipes/releases?q=motoko&expanded=true).
> Replace `<version>` with a release version (e.g. `v5.0.0`). See [available versions](https://github.com/dfinity/icp-cli-recipes/releases?q=motoko&expanded=true).

The canister must also be defined in `mops.toml`. The key in the `[canisters]` section must match the canister name in `icp.yaml`:

```toml
[toolchain]
moc = "1.8.2"

[canisters]
backend = "src/main.mo"
```

Compiler flags, per-canister args, and the Candid file are all configured in `mops.toml`. See the [mops documentation](https://mops.one/docs) for the full `[canisters]` schema.

## Configuration Parameters

| Parameter | Type | Required | Description | Default |
|-----------|---------|----------|----------------------------------------------|---------|
| main | string | Yes | Path to the main Motoko source file | |
| args | string | No | Additional arguments to pass to moc compiler (e.g., `--incremental-gc`) | |
| candid | string | No | Path to a custom Candid interface file. If not provided, the interface is auto-generated by the Motoko compiler | (auto-generated) |
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
| shrink | boolean | No | Remove unused functions and debug info to reduce file size | false |
| compress | boolean | No | Gzip compress the WASM file | false |

## Prerequisites

- `mops` (Motoko package manager) - this recipe uses `mops toolchain` to manage the Motoko compiler
- `mops` (Motoko package manager) — manages the toolchain, dependencies, and canister build
- `ic-wasm` (included with icp-cli installation)

> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), both `mops` and `ic-wasm` are already installed.
Expand All @@ -45,42 +53,63 @@ If mops is not installed, see: <https://mops.one/docs/install>
### Basic Example

```yaml
# icp.yaml
canisters:
- name: hello-world
recipe:
type: "@dfinity/motoko@<version>"
configuration:
main: src/main.mo
```

```toml
# mops.toml
[toolchain]
moc = "1.8.2"

[canisters]
hello-world = "src/main.mo"
```

### Advanced Example

```yaml
# icp.yaml
canisters:
- name: complex-backend
- name: backend
recipe:
type: "@dfinity/motoko@<version>"
configuration:
main: src/backend.mo
args: --incremental-gc
shrink: true
compress: true
metadata:
- name: "canister:type"
value: "backend"
- name: "language:version"
value: "0.10.0"
```

```toml
# mops.toml
[toolchain]
moc = "1.8.2"

[dependencies]
core = "2.5.0"

[moc]
args = ["--default-persistent-actors"]

[canisters.backend]
main = "src/main.mo"
candid = "backend.did"
```

## Build Process

When this recipe is executed:

1. Checks if `mops` is installed (used for Motoko toolchain management)
2. Compiles the specified Motoko entry file using `moc` via `mops toolchain`
3. Handles Candid interface: auto-generates from Motoko source, or uses the provided `candid` file
4. Injects compiler version metadata ("moc:version")
5. Injects template type metadata ("template:type" = "motoko")
1. Checks if `mops` and `ic-wasm` are installed
2. Runs `mops build <name>` which compiles the canister using the toolchain, dependencies, and compiler flags defined in `mops.toml`
3. Copies the built WASM to the icp-cli output path
4. Injects compiler version metadata (`moc:version`)
5. Injects template type metadata (`template:type` = `motoko`)
6. Injects any custom metadata specified in the configuration
7. Optionally removes unused functions if `shrink` is enabled
8. Optionally gzip compresses the WASM file if `compress` is enabled
Expand All @@ -95,40 +124,42 @@ my-project/
│ ├── main.mo # Entry point
│ ├── types.mo # Type definitions
│ └── utils.mo # Utility functions
├── .vessel/ # Package manager dependencies
└── icp.yaml # Build configuration
├── mops.toml # Toolchain, dependencies, canister config
└── icp.yaml # Build configuration
```

## Common Issues
## Migrating from v4

The `main`, `candid`, and `args` recipe parameters have been removed. Move them to `mops.toml`:

### Issue 1
| Before (`icp.yaml`) | After (`mops.toml`) |
|-----------------------------|--------------------------------------------|
| `main: src/main.mo` | `[canisters.backend] main = "src/main.mo"` |
| `candid: backend.did` | `[canisters.backend] candid = "backend.did"` |
| `args: --incremental-gc` | `[canisters.backend] args = ["--incremental-gc"]` |

**Problem**: `moc not found` error
**Solution**: Install the Motoko compiler following the instructions at <https://internetcomputer.org/docs/building-apps/getting-started/install>
The canister name in `icp.yaml` is used automatically — no additional recipe configuration is needed.

### Issue 2
## Common Issues

**Problem**: Compilation errors in Motoko code
**Solution**: Check your Motoko syntax and ensure all imports are correctly resolved
### "No Motoko canisters found in mops.toml configuration"

### Issue 3
The `[canisters]` section is missing from `mops.toml`, or the canister name does not match the `name` parameter in `icp.yaml`. Ensure the key in `[canisters]` exactly matches the `name` value in the recipe configuration.

**Problem**: Entry file not found
**Solution**: Verify the entry path is correct relative to your project root and the file exists
### "moc not found" error

### Issue 4
Install the Motoko compiler via mops: run `mops install` in your project directory. The toolchain version is set in `mops.toml` under `[toolchain]`.

**Problem**: Missing dependencies
**Solution**: Ensure all imported modules are available or install them using vessel package manager
### Compilation errors

Check your Motoko syntax and ensure all imports resolve. Run `mops check` for detailed diagnostics.

## Related Recipes

- [Rust Recipe](../rust/README.md) - For building Rust canisters
- [Pre-built Recipe](../prebuilt/README.md) - For using pre-compiled WASM files
- [Asset Canister Recipe](../asset-canister/README.md) - For frontend assets canister

Use this recipe when developing IC canisters in Motoko, the native language for the Internet Computer.

## Release History

See the [release history](https://github.com/dfinity/icp-cli-recipes/releases?q=motoko&expanded=true) for changelogs, version updates, and breaking changes.
11 changes: 3 additions & 8 deletions recipes/motoko/recipe.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
{{! A recipe for building a Motoko canister }}
{{! `main: string` Motoko file which contains the main actor }}
{{! `args: string` Additional arguments to pass to the moc compiler }}
{{! `candid: string` Optional, the path to the Candid interface file }}
{{! A recipe for building a Motoko canister using `mops build` }}
{{! `shrink: boolean` Optimizes the wasm with ic-wasm }}
{{! `compress: boolean` determines whether the wasm should be gzipped }}
{{! `metadata: [name: string, value: string]`: An array of name/value pairs that get injected into the wasm metadata section }}
Expand All @@ -19,7 +16,8 @@ build:

- type: script
commands:
- sh -c '$(mops toolchain bin moc) "{{ main }}" {{#if args}}{{ args }} {{/if}}{{#if candid}}--omit-metadata{{else}}--public-metadata{{/if}} candid:service $(mops sources) -o "$ICP_WASM_OUTPUT_PATH"'
- mops build "{{ _.canister.name }}" --output .mops/.build
- cp ".mops/.build/{{ _.canister.name }}.wasm" "$ICP_WASM_OUTPUT_PATH"

- type: script
commands:
Expand All @@ -28,9 +26,6 @@ build:
- type: script
commands:
- ic-wasm "$ICP_WASM_OUTPUT_PATH" -o "${ICP_WASM_OUTPUT_PATH}" metadata "template:type" -d "motoko" --keep-name-section
{{#if candid}}
- ic-wasm "$ICP_WASM_OUTPUT_PATH" -o "${ICP_WASM_OUTPUT_PATH}" metadata "candid:service" -f '{{ candid }}' -v public --keep-name-section
{{/if}}
{{#if metadata}}
{{#each metadata}}
- ic-wasm "$ICP_WASM_OUTPUT_PATH" -o "${ICP_WASM_OUTPUT_PATH}" metadata "{{ name }}" -d "{{ value }}" --keep-name-section
Expand Down
Loading