docs: add zig section (#1051)
Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This commit is contained in:
@@ -22,8 +22,3 @@ This example uses `@panic()` rather than `unreachable` to handle errors
|
||||
since `unreachable` emits a call to panic only in `Debug` and `ReleaseSafe`
|
||||
mode. In `ReleaseFast` and `ReleaseSmall` mode, it would lead into undefined
|
||||
behavior.
|
||||
|
||||
If building wasm with a pre-release version of Zig 0.10.0, use `-fstage1` to
|
||||
avoid [bugs in the new compiler][1].
|
||||
|
||||
[1]: https://github.com/ziglang/zig/wiki/Self-Hosted-Compiler-Upgrade-Guide#is-it-time-to-upgrade
|
||||
|
||||
@@ -13,6 +13,7 @@ to use Wasm built with "tinygo". Here are the included examples:
|
||||
|
||||
* [cargo-wasi](testdata/cargo-wasi) - Built via `cargo wasi build --release; mv ./target/wasm32-wasi/release/cat.wasm .`
|
||||
* [tinygo](testdata/tinygo) - Built via `tinygo build -o cat.wasm -scheduler=none --no-debug -target=wasi cat.go`
|
||||
* [zig](testdata/zig) - Built via `zig build-exe cat.zig -target=wasm32-wasi -OReleaseSmall`
|
||||
* [zig-cc](testdata/zig-cc) - Built via `zig cc cat.c -o cat.wasm --target=wasm32-wasi -O3`
|
||||
|
||||
To run the same example with zig-cc:
|
||||
|
||||
@@ -20,6 +20,7 @@ Below are notes wazero contributed so far, in alphabetical order by language.
|
||||
* [Go](go) e.g. `GOARCH=wasm GOOS=js go build -o X.wasm X.go`
|
||||
* [TinyGo](tinygo) e.g. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
* [Rust](rust) e.g. `rustc -o X.wasm --target wasm32-wasi X.rs`
|
||||
* [Zig](zig) e.g. `zig build-exe X.zig -target wasm32-wasi`
|
||||
|
||||
wazero is a runtime that embeds in Go applications, not a web browser. As
|
||||
such, these notes bias towards backend use of WebAssembly, not browser use.
|
||||
|
||||
196
site/content/languages/zig.md
Normal file
196
site/content/languages/zig.md
Normal file
@@ -0,0 +1,196 @@
|
||||
+++
|
||||
title = "Zig"
|
||||
+++
|
||||
|
||||
## Introduction
|
||||
|
||||
Beginning with 0.4.0 [Zig][1] can generate `%.wasm` files instead of
|
||||
architecture-specific binaries through three targets:
|
||||
|
||||
* `wasm32-emscripten`: mostly for browser (JavaScript) use.
|
||||
* `wasm32-freestanding`: for standalone use in or outside the browser.
|
||||
* `wasm32-wasi`: for use outside the browser.
|
||||
|
||||
This document is maintained by wazero, which is a WebAssembly runtime that
|
||||
embeds in Go applications. Hence, our notes focus on targets used outside the
|
||||
browser, tested by wazero: `wasm32-freestanding` and `wasm32-wasi`.
|
||||
|
||||
## Overview
|
||||
|
||||
When Zig compiles a `%.zig` file with a `wasm32-*` target, the output `%.wasm`
|
||||
depends on a subset of features in the [WebAssembly 2.0
|
||||
Core specification]({{< ref "/specs#core" >}}) and [WASI]({{< ref "/specs#wasi" >}}) host
|
||||
functions.
|
||||
|
||||
Unlike some compilers, Zig also supports importing custom host functions and
|
||||
exporting functions back to the host.
|
||||
|
||||
Here's a basic example of source in Zig:
|
||||
|
||||
```zig
|
||||
export fn add(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
The following is the minimal command to build a Wasm file.
|
||||
|
||||
```bash
|
||||
zig build-lib -dynamic -target wasm32-freestanding main.zig
|
||||
```
|
||||
|
||||
The resulting Wasm `export`s the `add` function so that the embedding host can
|
||||
call it, regardless of if the host is written in Zig or not.
|
||||
|
||||
Notice we are using `zig build-lib -dynamic`: this
|
||||
compiles the source as a library, i.e. without a `main` function.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This document includes notes contributed by the wazero community for Zig 0.10.1.
|
||||
While wazero includes Zig examples, and maintainers contribute to Zig, this
|
||||
isn't a Zig official document. For more help, consider the [WebAssembly Documentation][4]
|
||||
or joining the [#programming-discussion channel on
|
||||
Zig's Discord][5].
|
||||
|
||||
Meanwhile, please help us [maintain][6] this document and [star our GitHub
|
||||
repository][7], if it is helpful. Together, we can make WebAssembly easier on
|
||||
the next person.
|
||||
|
||||
## Constraints
|
||||
|
||||
Please read our overview of WebAssembly and
|
||||
[constraints]({{< ref "_index.md#constraints" >}}). In short, expect
|
||||
limitations in both language features and library choices when developing your
|
||||
software.
|
||||
|
||||
## Memory
|
||||
|
||||
The Zig language performs no memory management on behalf of the programmer.
|
||||
However, Zig has no default allocator. Instead, functions which need to allocate
|
||||
accept an `Allocator` parameter.
|
||||
|
||||
### Host Allocations
|
||||
|
||||
Sometimes a host function needs to allocate memory directly. For example, to write JSON
|
||||
of a given length before invoking an exported function to parse it.
|
||||
|
||||
```zig
|
||||
pub export fn configure(ptr: [*]const u8, size: u32) void {
|
||||
_configure(message[0..size]) catch |err| @panic(switch (err) {
|
||||
error.OutOfMemory => "out of memory",
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
The general flow is that the host allocates memory by calling an allocation
|
||||
function with the size needed. Then, it writes data, in this case JSON, to the
|
||||
memory offset (`ptr`). At that point, it can call a host function, ex
|
||||
`configure`, passing the `ptr` and `size` allocated. The guest Wasm (compiled
|
||||
from Zig) will be able to read the data. To ensure no memory leaks, the host
|
||||
calls a free function, with the same `ptr`, afterwards and unconditionally.
|
||||
|
||||
Note: wazero includes an [example project][9] that shows this.
|
||||
|
||||
The [zig example][9] does a few things of interest:
|
||||
* Uses `@ptrToInt` to change a Zig pointer to a numeric type
|
||||
* Uses `[*]u8` as an argument to take a pointer and slices it to build back a
|
||||
string
|
||||
* It also shows how to import a host function using the `extern` directive
|
||||
|
||||
To allow the host to allocate memory, you need to define your own `malloc` and
|
||||
`free` functions:
|
||||
```webassembly
|
||||
(func (export "malloc") (param $size i32) (result (;$ptr;) i32))
|
||||
(func (export "free") (param $ptr i32) (param $size i32))
|
||||
```
|
||||
|
||||
Because Zig easily allows end-users to [plug their own allocators][12], it relatively easy to
|
||||
export custom `malloc`/`free` pairs to the host.
|
||||
|
||||
For instance, the following code exports `malloc`, `free` from Zig's `page_allocator`:
|
||||
|
||||
```zig
|
||||
const allocator = std.heap.page_allocator;
|
||||
|
||||
pub export fn malloc(length: usize) ?[*]u8 {
|
||||
const buff = allocator.alloc(u8, length) catch return null;
|
||||
return buff.ptr;
|
||||
}
|
||||
|
||||
pub export fn free(buf: [*]u8, length: usize) void {
|
||||
allocator.free(buf[0..length]);
|
||||
}
|
||||
```
|
||||
|
||||
## System Calls
|
||||
|
||||
Please read our overview of WebAssembly and
|
||||
[System Calls]({{< ref "_index.md#system-calls" >}}). In short, WebAssembly is
|
||||
a stack-based virtual machine specification, so operates at a lower level than
|
||||
an operating system.
|
||||
|
||||
For functionality the operating system would otherwise provide, you must use
|
||||
the `wasm32-wasi` target. This imports host functions in
|
||||
[WASI]({{< ref "/specs#wasi" >}}).
|
||||
|
||||
Zig's standard library support for WASI is under active development.
|
||||
In general, you should favor use of the standard library when compiling against
|
||||
wasm32-wasi target (e.g. `std.io`).
|
||||
|
||||
Note: wazero includes an [example WASI project][10] including [source code][11]
|
||||
that implements `cat` without any WebAssembly-specific code.
|
||||
|
||||
## Concurrency
|
||||
|
||||
Please read our overview of WebAssembly and
|
||||
[concurrency]({{< ref "_index.md#concurrency" >}}). In short, the current
|
||||
WebAssembly specification does not support parallel processing.
|
||||
|
||||
## Optimizations
|
||||
|
||||
Below are some commonly used configurations that allow optimizing for size or
|
||||
performance vs defaults. Note that sometimes one sacrifices the other.
|
||||
|
||||
### Binary size
|
||||
|
||||
Those with `%.wasm` binary size constraints can change their source,
|
||||
e.g. picking a [different allocator][9b] or set `zig` flags to reduce it.
|
||||
|
||||
[`zig` flags][13]:
|
||||
Zig provides several flags to control binary size, speed of execution,
|
||||
safety checks. For instance you may use
|
||||
* `-ODebug`: Fast build, enabled safety checks, slower runtime performance,
|
||||
larger binary size
|
||||
* `-OReleaseSafe`: Medium runtime performance, enabled safety checks,
|
||||
slower compilation speed, larger binary size
|
||||
* `-OReleaseSmall`: Medium runtime performance, disabled safety checks,
|
||||
slower compilation speed, smaller binary size
|
||||
|
||||
### Performance
|
||||
|
||||
Those with runtime performance constraints can change their source or set
|
||||
`zig` flags to improve it.
|
||||
|
||||
[`zig` flags][13]:
|
||||
* `-OReleaseFast`: Enable additional optimizations, possibly at the cost of
|
||||
increased binary size.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### Why is my `%.wasm` binary so big?
|
||||
Zig defaults can be overridden for those who can sacrifice features or
|
||||
performance for a [smaller binary](#binary-size). After that, tuning your
|
||||
source code may reduce binary size further.
|
||||
|
||||
[1]: https://ziglang.org/download/0.4.0/release-notes.html
|
||||
[2]: https://ziglang.org/documentation/0.10.1/#WASI
|
||||
[4]: https://ziglang.org/documentation/0.10.1/#WebAssembly
|
||||
[5]: https://discord.gg/gxsFFjE
|
||||
[6]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages/zig.md
|
||||
[7]: https://github.com/tetratelabs/wazero/stargazers
|
||||
[9]: https://github.com/tetratelabs/wazero/tree/main/examples/allocation/zig
|
||||
[9b]: https://ziglang.org/documentation/0.10.1/#Memory
|
||||
[10]: https://github.com/tetratelabs/wazero/tree/main/imports/wasi_snapshot_preview1/example/testdata/zig
|
||||
[11]: https://github.com/tetratelabs/wazero/blob/main/imports/wasi_snapshot_preview1/example/testdata/zig/cat.zig
|
||||
[13]: https://ziglang.org/documentation/0.10.1/#Build-Mode
|
||||
Reference in New Issue
Block a user