Skip to content

Commit b78cd93

Browse files
authored
docs(guides): add guide for explaining how to compile custom chips to WASM (#254)
1 parent 0ead636 commit b78cd93

File tree

4 files changed

+132
-0
lines changed

4 files changed

+132
-0
lines changed
257 KB
Loading
21.5 KB
Loading
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
title: Compiling custom chips to WASM
3+
sidebar_label: Custom chips as WASM
4+
description: Compile your custom chips to WASM for use with VS Code or the Wokwi CLI
5+
keywords: [Visual Studio Code, VS Code, custom chip, compiling, WASM, web assembly, API, chips, chip, docker]
6+
---
7+
8+
import VsCodeDevContainerImage from './custom-chips-as-wasm-vscode-dev-container.png';
9+
import VsCodeRemoteContainerImage from './custom-chips-as-wasm-vscode-remote-container-button.png';
10+
11+
Custom components written with the [Chips API](/chips-api/getting-started) can be compiled into WebAssembly (WASM) for
12+
use with the Wokwi VS Code extension or the Wokwi CLI.
13+
14+
The WASM binary can be compiled by GitHub Actions, a container, or locally. This guide will cover all three
15+
approaches.
16+
17+
The simplest way to get started is by cloning/forking the [inverter-chip](https://github.com/wokwi/inverter-chip)
18+
example repository from the Wokwi GitHub. You can then compile locally, use the dev container feature from VS
19+
Code, or push to GitHub to compile the WASM binary. This repository will also be referenced multiple times throughout
20+
this guide, so it is worth having a look at.
21+
22+
## Configure your project
23+
Before compiling your chip, you should make sure your project is configured properly to ensure that they can work in
24+
Wokwi.
25+
26+
### Wokwi configuration
27+
A custom chip requires a `[[chip]]` key in `wokwi.toml`. This key specifies the name and binary used by the custom chip.
28+
Wokwi also requires a JSON file that describes the pinout of the chip. This JSON file should have the same name as the
29+
WASM binary, but with its extension changed to `.json` instead of `.wasm`, e.g. `inverter.chip.wasm` is paired with
30+
`inverter.chip.json`. To configure the chip JSON file properly, see the docs on [custom chip definitions](../chips-api/chip-json).
31+
32+
An example excerpt from `wokwi.toml`:
33+
```toml
34+
[[chip]]
35+
name = 'inverter' # To use the chip in diagram.json, add a part with "chip-inverter" type.
36+
binary = 'chips/inverter.chip.wasm'
37+
```
38+
39+
Multiple chips can be added to the same project by adding multiple `[[chip]]` keys, each with different `name` and
40+
`binary` values.
41+
42+
### Source files
43+
:::note
44+
If you are cloning/forking the inverter chip repository, then you can skip this section.
45+
:::
46+
47+
If you are setting up your project from scratch, you need to ensure that the Wokwi C API is present within your source
48+
files. It is available from [wokwi.com/api/chips/wokwi-api.h](https://wokwi.com/api/chips/wokwi-api.h).
49+
50+
You need to ensure that it is included in your project, otherwise you will not be able to make use of the Chips API.
51+
52+
## Compilation methods
53+
54+
### GitHub Actions
55+
56+
If you have cloned the inverter chip repository, then it has been configured and is ready for you to modify it to your
57+
needs. It will automatically compile the binary once a push is made to the repository, and will also automatically
58+
generate a GitHub release if you push a tag that starts with a "v", e.g. `v1.0.3`.
59+
60+
If you did not clone the inverter chip repository and are wanting to configure your own actions, then consider looking
61+
at the [build workflow file](https://github.com/wokwi/inverter-chip/blob/ff72418a11d9d56621731ab3d373c952b1b508ea/.github/workflows/build.yaml).
62+
If you do not want to use this action, then see the steps for compiling locally.
63+
64+
65+
### VS Code dev container
66+
The inverter chip repository comes with a dev container configuration file that will automatically handle setting up a
67+
Docker container for you to build your binaries in. To make use of this, simply open the custom chip folder in a
68+
container by pressing <kbd>F1</kbd> and searching for "Dev Containers: Open Folder in Container...".
69+
70+
<figure>
71+
<img src={VsCodeDevContainerImage} alt="Opening a dev container in VS Code via the command palette" />
72+
<figcaption>Opening a dev container in VS Code via the command palette</figcaption>
73+
</figure>
74+
75+
Alternatively, you can click the icon bottom left of the VS Code window, and click on "Reopen in Container".
76+
77+
<figure>
78+
<img src={VsCodeRemoteContainerImage} style={{margin: "auto"}} alt="Opening a dev container in VS Code via a dedicated button"/>
79+
<figcaption>Opening a dev container in VS Code via a dedicated button</figcaption>
80+
</figure>
81+
82+
Once done, you should be presented with a terminal window where you can now run `make`. This will run the `Makefile` in
83+
the repository, and your generated WASM files should appear in `dist/`.
84+
85+
### Docker
86+
You can use the prebuilt [wokwi/builder-clang-wasm](https://hub.docker.com/r/wokwi/builder-clang-wasm) image to compile
87+
your project in a Docker environment.
88+
89+
To get started, simply navigate to the root of your project and run:
90+
```bash
91+
docker run --rm -u 1000:1000 -v ${PWD}:/src wokwi/builder-clang-wasm:latest make
92+
```
93+
94+
After fetching the image, this will command automatically execute the `Makefile` in the project. In the case of the
95+
inverter example, it will create the `dist/` directory, compile the binary into `dist/chip.wasm` and copy `chip.json` to
96+
`dist/`.
97+
98+
You can enter an interactive session with the following:
99+
```bash
100+
docker run --rm -it -u 1000:1000 -v ${PWD}:/src wokwi/builder-clang-wasm:latest
101+
```
102+
103+
:::info
104+
The argument `-u 1000:1000` is required since otherwise you may run into issues with permissions (such as the container
105+
being unable to open files or create directories). If your computer has multiple users, you may have to update
106+
the value to something other than `1000` - check the output of the `id` command on the host to get the proper value.
107+
:::
108+
109+
110+
### Building locally
111+
112+
You will need to configure your environment to be able to build WASM assemblies locally. This part of the documentation
113+
is written with Ubuntu/Debian distros in mind, so you may have to adjust these instructions to your machine.
114+
115+
1. Install `wasi-libc` with `sudo apt install wasi-libc`
116+
2. Install the missing `libclang_rt.builtins-wasm32.a` library
117+
1. Download `libclang_rt-27.0.tar.gz` from the [wasi-sdk GitHub releases](https://github.com/WebAssembly/wasi-sdk/releases)
118+
2. Extract `libclang_rt-27.0/wasm32-unknown-wasi/libclang_rt.builtins.a` to `/usr/lib/llvm-???/lib/clang/???/lib/wasi/`
119+
:::info
120+
Replace the `???` in the path above with the currently installed LLVM version number on your system. Check by
121+
running `clang -v` and looking at the major release number.
122+
:::
123+
3. Rename the copied file from `libclang_rt.builtins.a` to `libclang_rt.builtins-wasm32.a`
124+
125+
You can now compile WASM binaries! To test, clone the inverter repository and run
126+
`clang --target=wasm32-unknown-wasi -nostartfiles -Wl,--import-memory -Wl,--export-table -Wl,--no-entry -Werror -o dist/chip.wasm src/main.c`.
127+
128+
You may have to update the `Makefile` to remove the `--sysroot` argument, as `wasi-libc` will be installed to a different
129+
directory than what `--sysroot` is set to.
130+
131+
If successful, you should now have `chip.wasm` under `dist/`!

sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313
'guides/circuitpython',
1414
'guides/esp32',
1515
'guides/esp32-wifi',
16+
'guides/custom-chips-to-wasm'
1617
],
1718
'Diagram Reference': [
1819
'diagram-format',

0 commit comments

Comments
 (0)