|
| 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/`! |
0 commit comments