github.com/AR1011/wazero@v1.0.5/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  
    97  - Uses `@ptrToInt` to change a Zig pointer to a numeric type
    98  - Uses `[*]u8` as an argument to take a pointer and slices it to build back a
    99    string
   100  - It also shows how to import a host function using the `extern` directive
   101  
   102  To allow the host to allocate memory, you need to define your own `malloc` and
   103  `free` functions:
   104  
   105  ```webassembly
   106  (func (export "malloc") (param $size i32) (result (;$ptr;) i32))
   107  (func (export "free") (param $ptr i32) (param $size i32))
   108  ```
   109  
   110  Because Zig easily allows end-users to [plug their own allocators][12], it relatively easy to
   111  export custom `malloc`/`free` pairs to the host.
   112  
   113  For instance, the following code exports `malloc`, `free` from Zig's `page_allocator`:
   114  
   115  ```zig
   116  const allocator = std.heap.page_allocator;
   117  
   118  pub export fn malloc(length: usize) ?[*]u8 {
   119      const buff = allocator.alloc(u8, length) catch return null;
   120      return buff.ptr;
   121  }
   122  
   123  pub export fn free(buf: [*]u8, length: usize) void {
   124      allocator.free(buf[0..length]);
   125  }
   126  ```
   127  
   128  ## System Calls
   129  
   130  Please read our overview of WebAssembly and
   131  [System Calls]({{< ref "_index.md#system-calls" >}}). In short, WebAssembly is
   132  a stack-based virtual machine specification, so operates at a lower level than
   133  an operating system.
   134  
   135  For functionality the operating system would otherwise provide, you must use
   136  the `wasm32-wasi` target. This imports host functions in
   137  [WASI]({{< ref "/specs#wasi" >}}).
   138  
   139  Zig's standard library support for WASI is under active development.
   140  In general, you should favor use of the standard library when compiling against
   141  wasm32-wasi target (e.g. `std.io`).
   142  
   143  Note: wazero includes an [example WASI project][10] including [source code][11]
   144  that implements `cat` without any WebAssembly-specific code.
   145  
   146  ## Concurrency
   147  
   148  Please read our overview of WebAssembly and
   149  [concurrency]({{< ref "_index.md#concurrency" >}}). In short, the current
   150  WebAssembly specification does not support parallel processing.
   151  
   152  ## Optimizations
   153  
   154  Below are some commonly used configurations that allow optimizing for size or
   155  performance vs defaults. Note that sometimes one sacrifices the other.
   156  
   157  ### Binary size
   158  
   159  Those with `%.wasm` binary size constraints can change their source,
   160  e.g. picking a [different allocator][9b] or set `zig` flags to reduce it.
   161  
   162  [`zig` flags][13]:
   163  Zig provides several flags to control binary size, speed of execution,
   164  safety checks. For instance you may use
   165  
   166  - `-ODebug`: Fast build, enabled safety checks, slower runtime performance,
   167    larger binary size
   168  - `-OReleaseSafe`: Medium runtime performance, enabled safety checks,
   169    slower compilation speed, larger binary size
   170  - `-OReleaseSmall`: Medium runtime performance, disabled safety checks,
   171    slower compilation speed, smaller binary size
   172  
   173  ### Performance
   174  
   175  Those with runtime performance constraints can change their source or set
   176  `zig` flags to improve it.
   177  
   178  [`zig` flags][13]:
   179  
   180  - `-OReleaseFast`: Enable additional optimizations, possibly at the cost of
   181    increased binary size.
   182  
   183  ## Frequently Asked Questions
   184  
   185  ### Why is my `%.wasm` binary so big?
   186  
   187  Zig defaults can be overridden for those who can sacrifice features or
   188  performance for a [smaller binary](#binary-size). After that, tuning your
   189  source code may reduce binary size further.
   190  
   191  [1]: https://ziglang.org/download/0.4.0/release-notes.html
   192  [2]: https://ziglang.org/documentation/0.10.1/#WASI
   193  [4]: https://ziglang.org/documentation/0.10.1/#WebAssembly
   194  [5]: https://discord.gg/gxsFFjE
   195  [6]: https://github.com/AR1011/wazero/tree/main/site/content/languages/zig.md
   196  [7]: https://github.com/AR1011/wazero/stargazers
   197  [9]: https://github.com/AR1011/wazero/tree/main/examples/allocation/zig
   198  [9b]: https://ziglang.org/documentation/0.10.1/#Memory
   199  [10]: https://github.com/AR1011/wazero/tree/main/imports/wasi_snapshot_preview1/example/testdata/zig
   200  [11]: https://github.com/AR1011/wazero/blob/main/imports/wasi_snapshot_preview1/example/testdata/zig/cat.zig
   201  [13]: https://ziglang.org/documentation/0.10.1/#Build-Mode