github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/site/content/languages/zig.md (about)

     1  +++
     2  title = "Zig"
     3  +++
     4  
     5  ## Introduction
     6  
     7  Beginning with 0.4.0 [Zig][1] can generate `%.wasm` files instead of
     8  architecture-specific binaries through three targets:
     9  
    10  * `wasm32-emscripten`: mostly for browser (JavaScript) use.
    11  * `wasm32-freestanding`: for standalone use in or outside the browser.
    12  * `wasm32-wasi`: for use outside the browser.
    13  
    14  This document is maintained by wazero, which is a WebAssembly runtime that
    15  embeds in Go applications. Hence, our notes focus on targets used outside the
    16  browser, tested by wazero: `wasm32-freestanding` and `wasm32-wasi`.
    17  
    18  ## Overview
    19  
    20  When Zig compiles a `%.zig` file with a `wasm32-*` target, the output `%.wasm`
    21  depends on a subset of features in the [WebAssembly 2.0 
    22  Core specification]({{< ref "/specs#core" >}}) and [WASI]({{< ref "/specs#wasi" >}}) host
    23  functions.
    24  
    25  Unlike some compilers, Zig also supports importing custom host functions and
    26  exporting functions back to the host.
    27  
    28  Here's a basic example of source in Zig:
    29  
    30  ```zig
    31  export fn add(a: i32, b: i32) i32 {
    32      return a + b;
    33  }
    34  ```
    35  
    36  The following is the minimal command to build a Wasm file.
    37  
    38  ```bash
    39  zig build-lib -dynamic -target wasm32-freestanding main.zig
    40  ```
    41  
    42  The resulting Wasm `export`s the `add` function so that the embedding host can
    43  call it, regardless of if the host is written in Zig or not.
    44  
    45  Notice we are using `zig build-lib -dynamic`: this
    46  compiles the source as a library, i.e. without a `main` function.
    47  
    48  ## Disclaimer
    49  
    50  This document includes notes contributed by the wazero community for Zig 0.10.1. 
    51  While wazero includes Zig examples, and maintainers contribute to Zig, this
    52  isn't a Zig official document. For more help, consider the [WebAssembly Documentation][4] 
    53  or joining the [#programming-discussion channel on 
    54  Zig's Discord][5]. 
    55  
    56  Meanwhile, please help us [maintain][6] this document and [star our GitHub
    57  repository][7], if it is helpful. Together, we can make WebAssembly easier on
    58  the next person.
    59  
    60  ## Constraints
    61  
    62  Please read our overview of WebAssembly and
    63  [constraints]({{< ref "_index.md#constraints" >}}). In short, expect
    64  limitations in both language features and library choices when developing your
    65  software.
    66  
    67  ## Memory
    68  
    69  The Zig language performs no memory management on behalf of the programmer. 
    70  However, Zig has no default allocator. Instead, functions which need to allocate 
    71  accept an `Allocator` parameter.
    72  
    73  ### Host Allocations
    74  
    75  Sometimes a host function needs to allocate memory directly. For example, to write JSON
    76  of a given length before invoking an exported function to parse it.
    77  
    78  ```zig
    79  pub export fn configure(ptr: [*]const u8, size: u32) void {
    80      _configure(message[0..size]) catch |err| @panic(switch (err) {
    81          error.OutOfMemory => "out of memory",
    82      });
    83  }
    84  ```
    85  
    86  The general flow is that the host allocates memory by calling an allocation
    87  function with the size needed. Then, it writes data, in this case JSON, to the
    88  memory offset (`ptr`). At that point, it can call a host function, ex
    89  `configure`, passing the `ptr` and `size` allocated. The guest Wasm (compiled
    90  from Zig) will be able to read the data. To ensure no memory leaks, the host
    91  calls a free function, with the same `ptr`, afterwards and unconditionally.
    92  
    93  Note: wazero includes an [example project][9] that shows this.
    94  
    95  The [zig example][9] does a few things of interest:
    96  * Uses `@ptrToInt` to change a Zig pointer to a numeric type
    97  * Uses `[*]u8` as an argument to take a pointer and slices it to build back a
    98  string
    99  * It also shows how to import a host function using the `extern` directive
   100  
   101  To allow the host to allocate memory, you need to define your own `malloc` and
   102  `free` functions:
   103  ```webassembly
   104  (func (export "malloc") (param $size i32) (result (;$ptr;) i32))
   105  (func (export "free") (param $ptr i32) (param $size i32))
   106  ```
   107  
   108  Because Zig easily allows end-users to [plug their own allocators][12], it relatively easy to 
   109  export custom `malloc`/`free` pairs to the host.
   110  
   111  For instance, the following code exports `malloc`, `free` from Zig's `page_allocator`:
   112  
   113  ```zig
   114  const allocator = std.heap.page_allocator;
   115  
   116  pub export fn malloc(length: usize) ?[*]u8 {
   117      const buff = allocator.alloc(u8, length) catch return null;
   118      return buff.ptr;
   119  }
   120  
   121  pub export fn free(buf: [*]u8, length: usize) void {
   122      allocator.free(buf[0..length]);
   123  }
   124  ```
   125  
   126  ## System Calls
   127  
   128  Please read our overview of WebAssembly and
   129  [System Calls]({{< ref "_index.md#system-calls" >}}). In short, WebAssembly is
   130  a stack-based virtual machine specification, so operates at a lower level than
   131  an operating system.
   132  
   133  For functionality the operating system would otherwise provide, you must use
   134  the `wasm32-wasi` target. This imports host functions in
   135  [WASI]({{< ref "/specs#wasi" >}}).
   136  
   137  Zig's standard library support for WASI is under active development. 
   138  In general, you should favor use of the standard library when compiling against 
   139  wasm32-wasi target (e.g. `std.io`).
   140  
   141  Note: wazero includes an [example WASI project][10] including [source code][11]
   142  that implements `cat` without any WebAssembly-specific code.
   143  
   144  ## Concurrency
   145  
   146  Please read our overview of WebAssembly and
   147  [concurrency]({{< ref "_index.md#concurrency" >}}). In short, the current
   148  WebAssembly specification does not support parallel processing.
   149  
   150  ## Optimizations
   151  
   152  Below are some commonly used configurations that allow optimizing for size or
   153  performance vs defaults. Note that sometimes one sacrifices the other.
   154  
   155  ### Binary size
   156  
   157  Those with `%.wasm` binary size constraints can change their source, 
   158  e.g. picking a [different allocator][9b] or set `zig` flags to reduce it.
   159  
   160  [`zig` flags][13]:
   161  Zig provides several flags to control binary size, speed of execution, 
   162  safety checks. For instance you may use
   163  * `-ODebug`: Fast build, enabled safety checks, slower runtime performance, 
   164    larger binary size
   165  * `-OReleaseSafe`: Medium runtime performance, enabled safety checks, 
   166    slower compilation speed, larger binary size
   167  * `-OReleaseSmall`: Medium runtime performance, disabled safety checks, 
   168    slower compilation speed, smaller binary size
   169  
   170  ### Performance
   171  
   172  Those with runtime performance constraints can change their source or set
   173  `zig` flags to improve it.
   174  
   175  [`zig` flags][13]:
   176  * `-OReleaseFast`: Enable additional optimizations, possibly at the cost of 
   177    increased binary size.
   178  
   179  ## Frequently Asked Questions
   180  
   181  ### Why is my `%.wasm` binary so big?
   182  Zig defaults can be overridden for those who can sacrifice features or
   183  performance for a [smaller binary](#binary-size). After that, tuning your
   184  source code may reduce binary size further.
   185  
   186  [1]: https://ziglang.org/download/0.4.0/release-notes.html
   187  [2]: https://ziglang.org/documentation/0.10.1/#WASI
   188  [4]: https://ziglang.org/documentation/0.10.1/#WebAssembly
   189  [5]: https://discord.gg/gxsFFjE
   190  [6]: https://github.com/bananabytelabs/wazero/tree/main/site/content/languages/zig.md
   191  [7]: https://github.com/bananabytelabs/wazero/stargazers
   192  [9]: https://github.com/bananabytelabs/wazero/tree/main/examples/allocation/zig
   193  [9b]: https://ziglang.org/documentation/0.10.1/#Memory
   194  [10]: https://github.com/bananabytelabs/wazero/tree/main/imports/wasi_snapshot_preview1/example/testdata/zig
   195  [11]: https://github.com/bananabytelabs/wazero/blob/main/imports/wasi_snapshot_preview1/example/testdata/zig/cat.zig
   196  [13]: https://ziglang.org/documentation/0.10.1/#Build-Mode