# Zig User Guide

Zig is a general-purpose programming language and toolchain for maintaining **robust, optimal, and reusable software**. A single `zig` executable is simultaneously a compiler for the Zig language, a drop-in C/C++ compiler, a cross-compilation toolchain, a build system, a package manager, a code formatter, and a test runner. This guide shows you how to install Zig and use every part of that toolchain from the command line.

> [!NOTE]
> This guide documents Zig **0.16.0** (development series). Zig is pre-1.0 software: the language and standard library still change between releases. Commands and flags described here are taken directly from the compiler source at the documented commit. Always cross-check against `zig <command> --help` for your installed version.

---

## Table of Contents

1. [Quick Start](#1-quick-start)
2. [Installation](#2-installation)
3. [The `zig` Command](#3-the-zig-command)
4. [Compiling and Running Single Files](#4-compiling-and-running-single-files)
5. [Optimization Modes](#5-optimization-modes)
6. [Building Projects with `zig build`](#6-building-projects-with-zig-build)
7. [The Package Manager](#7-the-package-manager)
8. [Cross-Compilation](#8-cross-compilation)
9. [Using Zig as a C/C++ Compiler](#9-using-zig-as-a-cc-compiler)
10. [Testing](#10-testing)
11. [Formatting Code](#11-formatting-code)
12. [Translating C to Zig](#12-translating-c-to-zig)
13. [The Standard Library](#13-the-standard-library)
14. [Inspecting Your Environment](#14-inspecting-your-environment)
15. [Utility and Drop-in Commands](#15-utility-and-drop-in-commands)
16. [Common Tasks (Recipes)](#16-common-tasks-recipes)
17. [Troubleshooting](#17-troubleshooting)
18. [FAQ](#18-faq)
19. [Command & Flag Reference](#19-command--flag-reference)
20. [Learning the Zig Language](#20-learning-the-zig-language)

---

## 1. Quick Start

Once Zig is on your `PATH`, you can write and run a program in under a minute.

Create a file called `hello.zig`:

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, {s}!\n", .{"world"});
}
```

Run it directly — Zig compiles to a native executable and runs it immediately:

```bash
zig run hello.zig
```

```text
Hello, world!
```

To produce a standalone, optimized binary instead of running it:

```bash
zig build-exe hello.zig -O ReleaseFast
./hello
```

```text
Hello, world!
```

To start a real, multi-file project with a build script and tests:

```bash
mkdir myproject && cd myproject
zig init
zig build run
```

> [!TIP]
> Five commands cover almost everything you will do day-to-day: `zig run` (compile + execute), `zig build-exe` (produce a binary), `zig build` (run your project's build script), `zig test` (run unit tests), and `zig fmt` (format source). Everything else is a refinement of these.

---

## 2. Installation

Zig ships as a **single self-contained executable** with a `lib/` directory beside it. There is no system-wide installation step, no runtime to install, and no dependency on a pre-existing C compiler — Zig bundles its own.

### 2.1 Download a prebuilt release

Official prebuilt tarballs are distributed from the Zig project's download page. Each archive contains the `zig` binary and the `lib/` directory that holds the standard library and the bundled libc sources.

=== "Linux / macOS"

    ```bash
    # Extract the archive you downloaded for your platform
    tar xf zig-<platform>-<version>.tar.xz
    # Move it somewhere on your PATH
    sudo mv zig-<platform>-<version> /opt/zig
    export PATH="/opt/zig:$PATH"
    ```

=== "Windows"

    ```powershell
    # Extract the .zip archive, then add the folder to your PATH
    Expand-Archive zig-windows-x86_64-<version>.zip -DestinationPath C:\zig
    setx PATH "%PATH%;C:\zig"
    ```

> [!IMPORTANT]
> The `zig` executable must stay next to its `lib/` directory. If you move the binary on its own, Zig will not find the standard library. If you must relocate the binary alone, point it back at the library with `--zig-lib-dir [path]` or the `ZIG_LIB_DIR` environment variable.

### 2.2 Verify the installation

```bash
zig version
```

```text
0.16.0-dev.xxxx+xxxxxxxxx
```

```bash
zig env
```

```text
{
 "zig_exe": "/opt/zig/zig",
 "lib_dir": "/opt/zig/lib",
 "std_dir": "/opt/zig/lib/std",
 "global_cache_dir": "/home/you/.cache/zig",
 "version": "0.16.0-dev.xxxx+xxxxxxxxx",
 "target": "x86_64-linux.6.1...6.1-gnu.2.31",
 "env": { ... }
}
```

If both commands print sensible output, Zig is installed correctly.

> [!NOTE]
> Zig has **no external runtime dependencies**. A Zig binary you build does not require Zig to be installed on the target machine. By default it does not even link a C library — programs are statically self-contained unless you explicitly opt into linking libc with `-lc`.

### 2.3 System requirements

| Requirement | Detail |
|---|---|
| Disk | A few hundred MB for the toolchain (it bundles libc sources for musl, glibc, and wasi, plus libc++ and compiler-rt) |
| C compiler | **Not required** — Zig is its own C/C++ compiler |
| LLVM | **Not required** for the default Zig backend; required only for `-fllvm`, LTO, and C/C++ compilation features marked *(requires LLVM extensions)* |
| Network | Only for `zig fetch` / `zig build` when a project declares package dependencies |

---

## 3. The `zig` Command

Run `zig` with no arguments (or `zig help`) to see the full command list:

```bash
zig help
```

```text
Usage: zig [command] [options]

Commands:

  build            Build project from build.zig
  fetch            Copy a package into global cache and print its hash
  init             Initialize a Zig package in the current directory

  build-exe        Create executable from source or object files
  build-lib        Create library from source or object files
  build-obj        Create object from source or object files
  test             Perform unit testing
  test-obj         Create object for unit testing
  run              Create executable and run immediately

  ast-check        Look for simple compile errors in any set of files
  fmt              Reformat Zig source into canonical form
  reduce           Minimize a bug report
  translate-c      Convert C code to Zig code

  ar               Use Zig as a drop-in archiver
  cc               Use Zig as a drop-in C compiler
  c++              Use Zig as a drop-in C++ compiler
  dlltool          Use Zig as a drop-in dlltool.exe
  lib              Use Zig as a drop-in lib.exe
  ranlib           Use Zig as a drop-in ranlib
  objcopy          Use Zig as a drop-in objcopy
  rc               Use Zig as a drop-in rc.exe

  env              Print lib path, std path, cache directory, and version
  help             Print this help and exit
  std              View standard library documentation in a browser
  libc             Display native libc paths file or validate one
  targets          List available compilation targets
  version          Print version number and exit
  zen              Print Zen of Zig and exit
```

The commands fall into a few groups:

| Group | Commands | What they do |
|---|---|---|
| **Project workflow** | `init`, `build`, `fetch` | Scaffold a package, run its build script, add dependencies |
| **Direct compilation** | `build-exe`, `build-lib`, `build-obj`, `run`, `test`, `test-obj` | Compile source/object files without a build script |
| **Source tooling** | `fmt`, `ast-check`, `translate-c`, `reduce` | Format, syntax-check, convert C, minimize bug reports |
| **Drop-in C toolchain** | `cc`, `c++`, `ar`, `ranlib`, `objcopy`, `rc`, `dlltool`, `lib` | Replace `gcc`/`clang`/`ar`/etc. |
| **Information** | `env`, `version`, `targets`, `libc`, `std`, `zen`, `help` | Inspect the toolchain |

> [!TIP]
> Every command accepts `-h` / `--help` for command-specific usage. The build/run/compile commands share a single large option set — see [Section 19](#19-command--flag-reference).

---

## 4. Compiling and Running Single Files

For one-off programs and experiments you do not need a build script. Five commands compile source (and object) files directly.

| Command | Result |
|---|---|
| `zig run [files] [-- args]` | Compile to a temporary executable and run it immediately, forwarding `args` |
| `zig build-exe [files]` | Create an executable |
| `zig build-lib [files]` | Create a static or dynamic library |
| `zig build-obj [files]` | Create a single object file |
| `zig test [files]` | Compile and run the file's unit tests |

### 4.1 `zig run`

```bash
zig run hello.zig
```

Pass arguments to your program after `--`:

```bash
zig run main.zig -- --name world --count 3
```

```text
Hello world (x3)
```

### 4.2 `zig build-exe`

```bash
zig build-exe hello.zig
./hello
```

Name the output and choose an optimization mode:

```bash
zig build-exe hello.zig --name greeter -O ReleaseSafe
./greeter
```

### 4.3 Supported input file types

`build-exe`/`build-lib`/`build-obj`/`run`/`test` accept far more than `.zig`. You can mix Zig, C, C++, assembly, and precompiled objects in a single command:

| Extension | File type |
|---|---|
| `.zig` | Zig source code |
| `.c` | C source code *(requires LLVM extensions)* |
| `.cpp` `.cxx` `.cc` `.C` `.c++` | C++ source code *(requires LLVM extensions)* |
| `.m` / `.mm` | Objective-C / Objective-C++ *(requires LLVM extensions)* |
| `.s` | Target-specific assembly |
| `.S` | Assembly with C preprocessor *(requires LLVM extensions)* |
| `.o` | ELF / Mach-O / WebAssembly object file |
| `.obj` | COFF (Windows) object file |
| `.a` | ELF / Mach-O / WebAssembly static library |
| `.lib` | COFF (Windows) static library |
| `.so` / `.dll` / `.dylib` | Shared object / DLL / dylib |
| `.tbd` | macOS text-based dylib definition |
| `.bc` | LLVM IR module *(requires LLVM extensions)* |

> [!NOTE]
> Features marked *(requires LLVM extensions)* are available only in Zig builds that include LLVM. The standalone Zig backend compiles Zig source without LLVM, but compiling C/C++ and consuming LLVM bitcode needs the LLVM-enabled toolchain (the default for official releases).

### 4.4 Controlling output artifacts

The `-femit-*` family controls what the compiler writes. Each has a `-fno-emit-*` counterpart, and most accept an optional `=path`:

```bash
# Emit assembly instead of a binary
zig build-obj math.zig -femit-asm=math.s -fno-emit-bin

# Emit a C header alongside the object
zig build-lib lib.zig -femit-h
```

| Flag | Effect |
|---|---|
| `-femit-bin[=path]` | (default) Output machine code |
| `-femit-asm[=path]` | Output `.s` assembly |
| `-femit-llvm-ir[=path]` | Output optimized LLVM IR `.ll` *(requires LLVM)* |
| `-femit-llvm-bc[=path]` | Output optimized LLVM bitcode `.bc` *(requires LLVM)* |
| `-femit-h[=path]` | Generate a C header `.h` |
| `-femit-docs[=path]` | Generate an HTML `docs/` directory |
| `-femit-implib[=path]` | (default for Windows DLLs) Produce an import `.lib` |

---

## 5. Optimization Modes

Zig has four build modes, selected with `-O`. They trade safety, speed, and binary size. There is **no separate "debug vs release" compiler** — the mode is a per-build choice.

| Mode | Optimizations | Safety checks | Use for |
|---|---|---|---|
| `Debug` | Off (default) | **On** | Development; fast compiles, runtime safety |
| `ReleaseSafe` | On | **On** | Production where safety matters more than max speed |
| `ReleaseFast` | On | Off | Maximum runtime performance |
| `ReleaseSmall` | On | Off | Smallest binary size |

```bash
zig build-exe app.zig -O ReleaseFast
```

> [!IMPORTANT]
> In `Debug` and `ReleaseSafe`, Zig inserts runtime **safety checks** (integer overflow, out-of-bounds access, invalid casts, `unreachable`, etc.) that turn undefined behavior into a defined panic. `ReleaseFast` and `ReleaseSmall` remove these checks for speed/size — bugs that were caught as panics become genuine undefined behavior. Prefer `ReleaseSafe` unless profiling proves you need `ReleaseFast`.

> [!TIP]
> Optimization mode is a *per-module* setting. With the `-M` module syntax (or in a build script) you can compile your own code in `ReleaseSafe` while a hot dependency uses `ReleaseFast`. When using `zig build`, request a mode with `--release[=fast|safe|small]` or expose it through `b.standardOptimizeOption()`.

---

## 6. Building Projects with `zig build`

For anything larger than a single file, Zig projects use a **build script written in Zig**: `build.zig`. Running `zig build` compiles and executes that script, which constructs a graph of build steps that the build runner then executes in parallel with automatic caching.

### 6.1 Scaffold a project

```bash
zig init
```

```text
info: created build.zig
info: created build.zig.zon
info: created src/main.zig
info: created src/root.zig
```

`zig init` creates a runnable, testable project:

| File | Purpose |
|---|---|
| `build.zig` | The build script (defines steps: build, run, test) |
| `build.zig.zon` | The package manifest (name, version, dependencies) |
| `src/main.zig` | Executable entry point (`pub fn main`) |
| `src/root.zig` | Library root module (re-exported public API) |

Use `-m` / `--minimal` for a bare template with fewer comments:

```bash
zig init --minimal
```

### 6.2 Anatomy of `build.zig`

A `build.zig` exposes one function, `pub fn build(b: *std.Build) void`, which *describes* the build rather than performing it. The functions in `std.Build` form a DSL for declaring modules, artifacts, and the dependencies between steps:

```zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    // Let the user pick target and optimization on the command line.
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // A reusable module (importable by consumers of this package).
    const mod = b.addModule("mymod", .{
        .root_source_file = b.path("src/root.zig"),
        .target = target,
    });

    // An executable whose root module imports the library module.
    const exe = b.addExecutable(.{
        .name = "myproject",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{ .{ .name = "mymod", .module = mod } },
        }),
    });

    // Install the binary into zig-out/ when `zig build` runs.
    b.installArtifact(exe);

    // Wire up `zig build run`.
    const run_step = b.step("run", "Run the app");
    const run_cmd = b.addRunArtifact(exe);
    run_step.dependOn(&run_cmd.step);
}
```

> [!NOTE]
> The build script is **declarative**: it mutates the build graph `b`, which an external runner then executes. Because the graph encodes dependencies between steps, the runner parallelizes the build automatically and the cache system knows exactly when a step can be skipped.

### 6.3 Running build steps

```bash
zig build              # Run the default install step (produces zig-out/)
zig build run          # Run a step named "run"
zig build test         # Run a step named "test"
zig build --list-steps # See every step this project defines
zig build --help       # Steps + project-specific options
```

The default output directory is `zig-out/`. Override it with `--prefix`:

| Flag | Effect |
|---|---|
| `-p`, `--prefix [path]` | Install location (default `zig-out`) |
| `--prefix-lib-dir [path]` | Where libraries are installed |
| `--prefix-exe-dir [path]` | Where executables are installed |
| `--prefix-include-dir [path]` | Where C headers are installed |

### 6.4 Choosing release mode and target

`zig build` exposes the same target and optimization choices as direct compilation:

```bash
# Release build for the host
zig build --release=fast

# Cross-compile (when build.zig uses standardTargetOptions)
zig build -Dtarget=aarch64-linux-musl -Doptimize=ReleaseSmall
```

`--release[=mode]` requests release mode (`fast`, `safe`, or `small`). Project-specific `-D` options are declared by the build script via `b.option()` and appear in `zig build --help` under **Project-Specific Options**.

### 6.5 Iterating: watch, summary, and parallelism

| Flag | Effect |
|---|---|
| `--watch` | Continuously rebuild when source files change |
| `--debounce <ms>` | Delay before rebuilding after a change is detected |
| `-j<N>` | Limit concurrent jobs (default: all CPU cores) |
| `--maxrss <bytes>` | Limit memory usage |
| `--summary [mode]` | Build summary: `all`, `new`, `failures`, `line`, `none` |
| `--prominent-compile-errors` | (via `--error-style`) Control error verbosity |
| `-l`, `--list-steps` | List available steps and exit |
| `--verbose` | Print each command before executing it |

```bash
# Rebuild and re-run tests on every save
zig build test --watch
```

> [!TIP]
> `zig build` has built-in **fuzzing** and a **web UI**. `zig build --fuzz` continuously searches your unit tests for failures (implies `--webui`); `zig build --time-report` forces a full rebuild and reports per-file compilation timings in the browser. Use `--webui[=ip]` to expose the interface on a specific address.

### 6.6 System integration

When a project links system libraries, the build runner can be told to use the host's installed libraries instead of fetched/built ones:

| Flag | Effect |
|---|---|
| `--search-prefix [path]` | Add a path to look for binaries, libraries, headers |
| `--sysroot [path]` | Set the system root directory |
| `--libc [file]` | Provide a libc paths file |
| `--system [pkgdir]` | Disable package fetching; enable all system integrations |
| `-fsys=[name]` / `-fno-sys=[name]` | Enable/disable a specific system integration |

---

## 7. The Package Manager

Zig's package manager is built into the toolchain. Dependencies are declared in `build.zig.zon` (a Zig Object Notation file) and consumed in `build.zig`.

### 7.1 The `build.zig.zon` manifest

```zig
.{
    .name = .myproject,
    .version = "0.1.0",
    .fingerprint = 0x1234567890abcdef, // auto-generated, never edit
    .minimum_zig_version = "0.16.0",
    .dependencies = .{
        .some_pkg = .{
            .url = "git+https://example.com/user/some_pkg.git#<commit>",
            .hash = "...",
        },
    },
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}
```

| Field | Required | Meaning |
|---|---|---|
| `name` | Yes | Enum literal, valid bare Zig identifier, ≤32 bytes. Default key consumers use to import this package. |
| `version` | Yes | [semver](https://semver.org/) string, ≤32 bytes |
| `fingerprint` | Yes | 64-bit globally-unique package id, **auto-generated and never changed**. Regenerate (delete + `zig build`) only when forking a still-maintained project. |
| `minimum_zig_version` | No | Advisory minimum Zig version (semver) |
| `dependencies` | No | Table of `url` + `hash` (or `path`) entries |
| `paths` | No | Files/directories included in the package's content hash |

> [!CAUTION]
> Do not hand-edit the `fingerprint`. It is how Zig detects that two packages are versions of the same project. Copying another project's fingerprint into your fork is, in the toolchain's own words, a **hostile** act that attempts to hijack the original's identity. Regenerate it (delete the field, run `zig build`) when forking.

### 7.2 Adding a dependency with `zig fetch`

`zig fetch` downloads a package into the global cache, computes its content hash, and (with `--save`) writes the entry into `build.zig.zon` for you:

```bash
zig fetch --save git+https://github.com/user/fun-tool.git
zig fetch --save https://example.com/user/tool/archive/refs/heads/master.tar.gz
```

A `<url>` may point to a `git+http`/`git+https` server, a (optionally compressed) tarball, or a git bundle file. A `<path>` fetches from a local directory.

| Flag | Effect |
|---|---|
| `--save` | Add the fetched package to `build.zig.zon` |
| `--save=[name]` | Save under a specific dependency name |
| `--save-exact` | Save and store the URL verbatim |
| `--global-cache-dir [path]` | Override the global cache directory |
| `--debug-hash` | Print verbose hash information |

In `build.zig`, pull the dependency into your build graph:

```zig
const dep = b.dependency("fun_tool", .{ .target = target, .optimize = optimize });
exe.root_module.addImport("fun_tool", dep.module("fun_tool"));
```

### 7.3 Fetching the whole dependency tree

```bash
zig build --fetch          # Fetch needed (lazy) dependencies and exit
zig build --fetch=all      # Fetch every dependency, even lazy ones
```

> [!NOTE]
> Dependencies are content-addressed by hash and stored in the **global cache** (see `zig env`'s `global_cache_dir`), shared across all your projects. A given package version is downloaded once and reused everywhere.

---

## 8. Cross-Compilation

Cross-compilation is Zig's signature feature. Because the toolchain **bundles the libc sources** for every supported target, you can compile for any supported OS/architecture from any host — no cross-toolchain, no sysroot, no extra downloads.

### 8.1 The `-target` triple

A target is written `<arch><sub>-<os>-<abi>`:

```bash
# From an x86-64 Linux host, build a Windows ARM64 executable:
zig build-exe hello.zig -target aarch64-windows-gnu

# A statically-linked Linux musl binary:
zig build-exe hello.zig -target x86_64-linux-musl -O ReleaseSmall

# A 64-bit RISC-V Linux binary:
zig build-exe hello.zig -target riscv64-linux-musl
```

List everything the compiler can target:

```bash
zig targets
```

This prints the available architectures, operating systems, ABIs, CPUs, and CPU feature sets as JSON.

### 8.2 Selecting a specific CPU

```bash
# Target a baseline CPU for maximum portability
zig build-exe app.zig -target x86_64-linux -mcpu=baseline

# Target a specific microarchitecture
zig build-exe app.zig -target x86_64-linux -mcpu=znver3

# Native CPU with all detected features (the default for native builds)
zig build-exe app.zig -mcpu=native
```

### 8.3 Glibc version selection

When targeting GNU/Linux you can pin a specific glibc version directly in the triple, and Zig builds the matching stub libraries on demand:

```bash
# Link against glibc 2.19 or later
zig build-exe app.zig -target x86_64-linux-gnu.2.19
```

> [!IMPORTANT]
> Zig supports glibc versions back to **2.17** (2012) for Zig programs that use the standard library, and back to **2.2.5** when used purely as a C compiler (`zig cc`). The glibc "libraries" Zig generates are stub libraries used only for compile-time linking — the real glibc on the target machine provides the implementations at run time.

### 8.4 Object format override

```bash
zig build-obj app.zig -ofmt=wasm     # WebAssembly
zig build-obj app.zig -ofmt=c        # Transpile to C source
```

Supported `-ofmt` values: `elf`, `c`, `wasm`, `coff`, `macho`, `spirv`, `plan9` (`hex` and `raw` are planned).

> [!TIP]
> `-ofmt=c` makes Zig emit portable C source instead of machine code — useful for bootstrapping onto platforms without a native Zig backend, or for embedding Zig logic into a C build.

---

## 9. Using Zig as a C/C++ Compiler

`zig cc` and `zig c++` are **drop-in replacements** for `gcc`/`clang` and `g++`/`clang++`. They accept Clang-compatible flags and inherit Zig's bundled headers and cross-compilation.

```bash
# Compile a C program exactly as you would with cc
zig cc -o hello hello.c

# Cross-compile C to Windows from Linux:
zig cc -o hello.exe hello.c -target x86_64-windows-gnu

# Use it as your project's CC:
CC="zig cc" CXX="zig c++" ./configure
make
```

Because Zig bundles musl, glibc stubs, wasi-libc, libc++, libc++abi, libunwind, and compiler-rt, `zig cc` can cross-compile C and C++ projects to dozens of targets with no additional toolchain. This is why many non-Zig projects adopt `zig cc` purely as a portable cross-compiler.

> [!NOTE]
> `zig cc` is a thin wrapper over the bundled Clang frontend; it understands GCC/Clang command-line conventions including `-I`, `-L`, `-l`, `-D`, `-O2`, `-std=`, `-Wall`, response files, and so on. Mixing C and Zig in one `build-exe`/`build-lib` invocation works because the same machinery backs both.

### 9.1 The other drop-in tools

Zig also stands in for the rest of a typical C toolchain, so a build system can call a single `zig` for everything:

| Command | Replaces |
|---|---|
| `zig cc` | `cc` / `clang` |
| `zig c++` | `c++` / `clang++` |
| `zig ar` | `ar` (archiver) |
| `zig ranlib` | `ranlib` |
| `zig lib` | `lib.exe` (MSVC librarian) |
| `zig objcopy` | `objcopy` |
| `zig rc` | `rc.exe` (Windows resource compiler) |
| `zig dlltool` | `dlltool` |

---

## 10. Testing

Zig has a **built-in test runner**. Tests are declared inline with the `test` keyword and run with `zig test` or a `test` step in `zig build`.

```zig
const std = @import("std");
const expect = std.testing.expect;

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "add works" {
    try expect(add(2, 3) == 5);
}
```

```bash
zig test mymodule.zig
```

```text
1/1 mymodule.test.add works... OK
All 1 tests passed.
```

### 10.1 Test options

| Flag | Effect |
|---|---|
| `--test-filter [text]` | Run only tests whose name contains `text` |
| `--test-cmd [arg]` | Run the test binary under a wrapper command (one arg at a time) |
| `--test-cmd-bin` | Append the test binary path to the wrapper command |
| `--test-no-exec` | Compile the test binary without running it |
| `--test-runner [path]` | Use a custom test runner |

```bash
# Run only tests mentioning "parser"
zig test src/parser.zig --test-filter parser

# Cross-compile tests and run them under QEMU
zig test app.zig -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin
```

> [!TIP]
> When running tests through `zig build`, add `--fuzz` to continuously search for failing inputs, and `--test-timeout <dur>` (e.g. `--test-timeout 30s`) to terminate tests that hang. The test runner reports memory leaks automatically when you use `std.testing.allocator`.

---

## 11. Formatting Code

`zig fmt` rewrites Zig source into the language's single canonical style — there are no formatting options to bikeshed.

```bash
# Format files and directories in place (recursive)
zig fmt src/

# Check formatting in CI without modifying files
zig fmt --check src/
```

```text
src/main.zig
src/parser.zig
```

| Flag | Effect |
|---|---|
| `--check` | List non-conforming files and exit non-zero if any (does not modify) |
| `--stdin` | Read from stdin, write formatted output to stdout |
| `--ast-check` | Run `zig ast-check` on every file while formatting |
| `--exclude [file]` | Exclude a file or directory |
| `--zon` | Treat all inputs as ZON regardless of extension |
| `--color [auto\|off\|on]` | Colored error messages |

> [!IMPORTANT]
> `zig fmt` (without `--check`) **modifies files in place**. Run it on a clean working tree or use `--check` in automated pipelines.

> [!TIP]
> `zig ast-check [file]` performs a fast syntax/semantic sanity check without producing any output binary — ideal for editor integrations and pre-commit hooks.

---

## 12. Translating C to Zig

`zig translate-c` converts a C source file into equivalent Zig code, printed to stdout. It is how `@cImport` works under the hood and is useful for porting C to Zig or for inspecting how a C API maps into the language.

```bash
zig translate-c -lc header_demo.c > demo.zig
```

`translate-c` accepts the same target and include-path flags as the compile commands (`-target`, `-I`, `-D`, `-isystem`, etc.), so you can translate a header as it would appear for a specific platform.

> [!NOTE]
> `translate-c` requires the LLVM/Clang-enabled toolchain (it parses C through Clang). The output is real, compilable Zig — read it, edit it, and commit it, or `@cImport` the header directly and let Zig translate it on the fly.

---

## 13. The Standard Library

The standard library lives under `lib/std/` and is imported as `@import("std")`. It is large and batteries-included. The most-used namespaces:

| Namespace | Contents |
|---|---|
| `std.mem` | Memory utilities: `Allocator`, copying, comparison, slicing, tokenizing |
| `std.heap` | Allocators: `GeneralPurposeAllocator`, `ArenaAllocator`, `page_allocator`, `FixedBufferAllocator` |
| `std.fmt` | Formatting: `std.fmt.allocPrint`, format strings, parsing numbers |
| `std.fs` | Filesystem: files, directories, paths, walking |
| `std.io` / `std.Io` | Readers, writers, buffered streams |
| `std.process` | Args, environment variables, child processes, exit |
| `std.ArrayList` | Growable array |
| `std.AutoHashMap` / `std.StringHashMap` | Hash maps |
| `std.json` | JSON parse/stringify |
| `std.crypto` | Hashes, AEAD ciphers, signatures, KDFs |
| `std.http` | HTTP client and server |
| `std.Thread` | Threads, mutexes, condition variables |
| `std.testing` | Test assertions and the testing allocator |
| `std.math` | Math functions and constants |
| `std.Build` | The build-system DSL used in `build.zig` |
| `std.Target` | Target description (arch/os/abi/cpu) |
| `std.debug` | `print`, stack traces, assertions |
| `std.sort` | Sorting algorithms |
| `std.unicode` | UTF-8 / UTF-16 handling |

Other namespaces include `atomic`, `base64`, `compress`, `dwarf`, `elf`, `macho`, `coff`, `pdb`, `tar`, `zip`, `time`, `Uri`, `SemanticVersion`, `Random`, `simd`, `enums`, `meta`, `ascii`, and the binary-format helpers.

### 13.1 Browse the standard library docs locally

```bash
zig std
```

This starts a local web server and opens the standard library's generated API documentation in your browser, exactly matching your installed version.

> [!TIP]
> Allocators are explicit in Zig — most standard-library containers and functions take an `Allocator` parameter. For application code, `std.heap.GeneralPurposeAllocator` (debug builds, leak detection) and `std.heap.ArenaAllocator` (bulk-free) are the common choices; `std.heap.page_allocator` is a simple fallback.

---

## 14. Inspecting Your Environment

```bash
zig version        # Just the version string
zig env            # Full environment as JSON
zig targets        # All supported targets/CPUs/features as JSON
zig zen            # The Zen of Zig
```

`zig env` reports the values Zig resolved for this invocation:

| Field | Meaning |
|---|---|
| `zig_exe` | Path to the running `zig` binary |
| `lib_dir` | Zig installation `lib/` directory |
| `std_dir` | Standard library directory |
| `global_cache_dir` | Where fetched packages and global build artifacts are cached |
| `version` | Compiler version |
| `target` | The native target triple |
| `env` | Resolved environment variables affecting Zig |

The Zen of Zig captures the language's design philosophy:

```text
 * Communicate intent precisely.
 * Edge cases matter.
 * Favor reading code over writing code.
 * Only one obvious way to do things.
 * Runtime crashes are better than bugs.
 * Compile errors are better than runtime crashes.
 * Incremental improvements.
 * Avoid local maximums.
 * Reduce the amount one must remember.
 * Focus on code rather than style.
 * Resource allocation may fail; resource deallocation must succeed.
 * Memory is a resource.
 * Together we serve the users.
```

---

## 15. Utility and Drop-in Commands

### 15.1 `zig libc`

Detect or validate a libc installation paths file, used for native compilation against a system libc:

```bash
# Print the detected native libc paths (save and edit for cross-compiling)
zig libc > my-libc.txt

# Validate a paths file you wrote
zig libc my-libc.txt

# Print the include directories for a target
zig libc -target x86_64-linux-gnu -includes
```

Pass the resulting file to any compile command with `--libc my-libc.txt`.

### 15.2 `zig objcopy`

```bash
zig objcopy [options] input output
```

A drop-in `objcopy` for stripping, format conversion, and section manipulation of object files and binaries.

### 15.3 `zig reduce`

`zig reduce` minimizes a Zig source file that triggers a compiler bug, repeatedly shrinking it while a check still reproduces the failure — invaluable when filing a bug report against the compiler.

### 15.4 `zig ast-check`

```bash
zig ast-check src/main.zig
```

Fast syntax and early-semantic checking with no output artifact. Used by editors and as a lightweight pre-commit gate.

---

## 16. Common Tasks (Recipes)

**Run a script-style program quickly**

```bash
zig run tool.zig -- arg1 arg2
```

**Produce a small, statically-linked Linux binary**

```bash
zig build-exe app.zig -target x86_64-linux-musl -O ReleaseSmall -fstrip
```

**Build a shared library with a C header**

```bash
zig build-lib mylib.zig -dynamic -femit-h --name mylib
```

**Cross-compile a C project with Zig as the compiler**

```bash
CC="zig cc -target aarch64-linux-musl" make
```

**Continuously test on save**

```bash
zig build test --watch
```

**Add and use a dependency**

```bash
zig fetch --save git+https://github.com/user/pkg.git
# then in build.zig: b.dependency("pkg", .{...})
zig build
```

**Strip debug info from an existing binary**

```bash
zig objcopy --strip-all app app-stripped
```

**Emit assembly to inspect codegen**

```bash
zig build-obj hot.zig -O ReleaseFast -femit-asm=hot.s -fno-emit-bin
```

---

## 17. Troubleshooting

### Error: `unable to find zig installation directory`

**Cause** — The `zig` binary was moved away from its `lib/` directory, so it cannot locate the standard library.
**Solution** — Keep `zig` next to `lib/`, or pass `--zig-lib-dir /path/to/lib` (or set `ZIG_LIB_DIR`).
**Prevention** — Install the toolchain as a unit; symlink the binary onto your `PATH` instead of copying it.

### Error: `error: unable to parse command line parameters: NestedResponseFile`

**Cause** — `zig cc` was given a response file (`@file`) that itself references another `@file`. Nested `@` response files are not currently supported (see issue [#24386](https://github.com/ziglang/zig/issues/24386)).
**Solution** — Flatten the response files into a single non-nested `@args` file, or pass the arguments directly.
**Prevention** — Avoid build systems that emit nested response files when using `zig cc`.

### Error: `'Io.File' has no member named 'WriteError'`

**Cause** — Code written for an older standard-library API. The `std.Io` / `std.fs` interfaces change across pre-1.0 releases (see issue [#25857](https://github.com/ziglang/zig/issues/25857)).
**Solution** — Update the code to the current API, or pin the Zig version your code was written for. Check `zig std` for the exact signatures of your installed version.
**Prevention** — Set `minimum_zig_version` in `build.zig.zon` and test against the Zig version you target.

### Error: a C/C++ feature reports *requires LLVM extensions*

**Cause** — You invoked a feature (compiling `.c`/`.cpp`, `-flto`, `-femit-llvm-ir`) on a Zig build that does not include LLVM.
**Solution** — Use an official release (LLVM-enabled) or a toolchain built with LLVM.
**Prevention** — Reserve the standalone (no-LLVM) backend for pure-Zig compilation.

### Error: linker cannot find a system library (`-lfoo`)

**Cause** — The library is not on the search path, or you are cross-compiling and the target library is unavailable.
**Solution** — Add `-L/path/to/libs`, supply a libc paths file with `--libc`, or use `--search-prefix` / `--sysroot` under `zig build`.
**Prevention** — For portable builds, prefer statically linking or targeting `musl` so no system libraries are needed.

### Build is slow or uses too much memory

**Cause** — Default parallelism uses all cores/memory; large `comptime` work can be heavy.
**Solution** — Limit with `-j<N>` and `--maxrss <bytes>`; use `--skip-oom-steps` to skip steps that would exceed the memory limit; enable `-fincremental` for faster rebuilds.
**Prevention** — Keep `comptime` evaluation bounded; use `--watch` so only changed steps rebuild.

### `zig build` cannot fetch a dependency

**Cause** — Network access is blocked, or the dependency hash/URL in `build.zig.zon` is wrong.
**Solution** — Run `zig build --fetch` to fetch explicitly; re-run `zig fetch --save <url>` to refresh the hash; check that the URL points to a git server, tarball, or git bundle.
**Prevention** — Commit `build.zig.zon` with pinned hashes; pre-fetch with `--fetch=all` in CI.

### A program crashes only in `ReleaseFast`

**Cause** — `ReleaseFast`/`ReleaseSmall` disable the runtime safety checks that turned undefined behavior into panics in `Debug`/`ReleaseSafe`.
**Solution** — Reproduce in `ReleaseSafe` (`-O ReleaseSafe`) to get a defined panic and a stack trace, then fix the underlying undefined behavior.
**Prevention** — Test in `ReleaseSafe`; only switch to `ReleaseFast` for code paths proven correct and profiled as hot.

---

## 18. FAQ

**Q: Do I need to install LLVM, GCC, or Clang to use Zig?**
No. The `zig` executable is a complete toolchain. It compiles Zig without LLVM (default backend) and includes its own bundled Clang for C/C++ work. You do not need a pre-existing compiler.

**Q: Do programs I build require Zig (or a runtime) to be installed on the target?**
No. Zig produces standalone native binaries with no runtime. By default they do not even link libc — they are statically self-contained unless you opt into `-lc` or dynamic linking.

**Q: How is cross-compilation "free"?**
Zig bundles the libc *sources* (musl, glibc stubs, wasi-libc) plus libc++, compiler-rt, and libunwind. It builds exactly what a given target needs on demand, so any host can target any supported platform with no extra toolchain or sysroot.

**Q: What is the difference between `zig run` and `zig build run`?**
`zig run file.zig` compiles and runs a single file directly. `zig build run` executes the `run` step defined in your project's `build.zig` (which can involve many modules, dependencies, and custom steps).

**Q: Why is there no config file for `zig fmt`?**
By design. Zig has exactly one canonical style; `zig fmt` enforces it with no options, eliminating formatting debates.

**Q: What does `-O ReleaseSafe` give me that `ReleaseFast` does not?**
Runtime safety checks (overflow, bounds, invalid casts, `unreachable`) are kept on in `ReleaseSafe` while optimizations are enabled. `ReleaseFast` removes those checks for maximum speed.

**Q: How do I see every flag for a command?**
Run `zig <command> --help`. The build/compile commands share one large option set; `zig build --help` additionally lists your project's `-D` options.

**Q: How do I pick which CPU to optimize for?**
Use `-mcpu`. `-mcpu=native` (default for native builds) uses your host CPU's features; `-mcpu=baseline` maximizes portability; `-mcpu=<name>` targets a specific microarchitecture. `zig targets` lists valid CPU names.

**Q: Is Zig stable / production-ready?**
Zig is pre-1.0. The language and standard library still change between releases. Many teams ship Zig (and `zig cc`) in production, but you should pin a version and expect to update code across releases.

**Q: Where do I report a compiler bug?**
Minimize it with `zig reduce` first, then file an issue. A small reproducer dramatically speeds up triage.

**Q: Can I compile to WebAssembly?**
Yes — `-target wasm32-wasi` (or `wasm32-freestanding`) and/or `-ofmt=wasm`. The WebAssembly-specific link options (`--import-memory`, `--export-memory`, `--initial-memory`, `--max-memory`, `--shared-memory`, `--export=`) are available on the compile commands.

**Q: How do I run my unit tests on a different architecture?**
Cross-compile the test binary and run it under an emulator: `zig test app.zig -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin`. Under `zig build`, the runner integrates with QEMU/Wine/Rosetta/wasmtime via `-fqemu`, `-fwine`, `-frosetta`, `-fwasmtime`.

---

## 19. Command & Flag Reference

### 19.1 General options (compile/run/test commands)

| Flag | Effect |
|---|---|
| `-h`, `--help` | Print command-specific help |
| `--color [auto\|off\|on]` | Colored error messages |
| `-j<N>` | Limit concurrent jobs |
| `-fincremental` / `-fno-incremental` | Enable/disable incremental compilation |
| `--cache-dir [path]` | Override the local cache directory |
| `--global-cache-dir [path]` | Override the global cache directory |
| `--zig-lib-dir [path]` | Override the Zig `lib/` directory |
| `--show-builtin` | Print the source of `@import("builtin")` and exit |

### 19.2 Global compile options

| Flag | Effect |
|---|---|
| `--name [name]` | Output/compilation-unit name |
| `--libc [file]` | libc paths file |
| `-x language` | Treat subsequent inputs as `language` |
| `--dep [[import=]name]` | Add an entry to the next module's import table |
| `-M[name][=src]` | Create a module from current per-module settings (first `-M` is the main module) |
| `--error-limit [num]` | Max number of distinct error values |
| `-fllvm` / `-fno-llvm` | Force/prevent the LLVM codegen backend |
| `-fclang` / `-fno-clang` | Force/prevent Clang as the C/C++ backend |
| `-fPIE` / `-fno-PIE` | Position-independent executable |
| `-flto` / `-fno-lto` | Link-time optimization *(requires LLVM)* |
| `-freference-trace[=num]` / `-fno-reference-trace` | Lines of reference trace per error |
| `-ffunction-sections` / `-fdata-sections` | Each function/datum in its own section |
| `-municode` | (Windows) use `wmain`/`wWinMain` entry |
| `--time-report` | Send timing diagnostics to `--listen` clients |

### 19.3 Per-module compile options

| Flag | Effect |
|---|---|
| `-target [name]` | `<arch><sub>-<os>-<abi>` target triple |
| `-O [Debug\|ReleaseFast\|ReleaseSafe\|ReleaseSmall]` | Optimization mode |
| `-ofmt=[elf\|c\|wasm\|coff\|macho\|spirv\|plan9]` | Object format override |
| `-mcpu [cpu]` | Target CPU and feature set |
| `-mcmodel=[model]` | Code model (`default`, `small`, `kernel`, `large`, `medany`, …) |
| `-fPIC` / `-fno-PIC` | Position-independent code |
| `-fstack-check` / `-fstack-protector` | Stack probing / protection |
| `-fsanitize-c[=trap\|full]` / `-fno-sanitize-c` | C undefined-behavior detection |
| `-fsanitize-thread` / `-fno-sanitize-thread` | Thread Sanitizer |
| `-ffuzz` / `-fno-fuzz` | Fuzz-testing instrumentation |
| `-funwind-tables` / `-fno-unwind-tables` | Unwind table generation |
| `-fsingle-threaded` | Assume a single thread |
| `-fstrip` / `-fno-strip` | Omit/keep debug symbols |
| `-I[dir]`, `-isystem [dir]`, `-idirafter [dir]` | C include search paths |
| `-D[macro]=[value]` | Define a C macro |
| `-cflags [flags] --` | Extra flags for the next C source files |

### 19.4 Common link options

| Flag | Effect |
|---|---|
| `-l[lib]`, `--library [lib]` | Link a system library (if used) |
| `-L[dir]`, `--library-directory [dir]` | Library search path |
| `-rpath [path]` | Runtime library search path |
| `-static` / `-dynamic` | Force static/dynamic linking |
| `-T[script]`, `--script [script]` | Custom linker script |
| `--dynamic-linker [path]` / `--no-dynamic-linker` | Dynamic interpreter path |
| `-flld` / `-fno-lld` | Force/prevent LLD as the linker |
| `--gc-sections` / `--no-gc-sections` | Remove unreachable functions/data |
| `--build-id[=style]` | Embed a build ID (`fast`, `sha1`, `md5`, `uuid`, `none`, …) |
| `-z [arg]` | Linker extension flags (`now`, `relro`, `defs`, `notext`, …) |
| `--stack [size]` | Override default stack size |
| WebAssembly: `--import-memory`, `--export-memory`, `--initial-memory=`, `--max-memory=`, `--shared-memory`, `--export=` | WASM linear-memory and export control |
| Darwin: `-framework [name]`, `-F[dir]`, `-install_name=`, `-dead_strip` | macOS frameworks and linker behavior |

> [!NOTE]
> This reference is a curated subset. For the exhaustive, version-exact list run `zig build-exe --help`; for the build runner run `zig build --help`.

---

## 20. Learning the Zig Language

This guide covers the **toolchain** — how to drive the `zig` binary. The Zig *language* itself (syntax, `comptime`, error unions, optionals, generics via types-as-values, allocators, async, the full type system) is documented in the project's canonical **Language Reference** that ships with every Zig release as `doc/langref.html.in` and is published online by the Zig project.

The language reference is the authoritative, exhaustive source for language semantics. Its major sections include:

- **Fundamentals** — Hello World, Comments, Values, Primitive Types, Variables, Integers, Floats, Operators
- **Aggregate types** — Arrays, Vectors (SIMD), Pointers, Slices, `struct` (incl. `extern`/`packed`), `enum`, `union`/Tagged unions, `opaque`, Tuples
- **Control flow** — Blocks, `switch` (incl. labeled/exhaustive), `while`, `for`, `if`, `defer`/`errdefer`
- **Functions and errors** — Functions, Errors and error unions, Optionals
- **Compile-time** — `comptime`, generic data structures, `@import`, builtins
- **Testing** — Test declarations, doctests, the testing namespace
- **C interop** — `@cImport`, `extern`, calling conventions, translate-c
- **Memory** — Allocators, alignment, sentinel-terminated pointers/arrays/slices

> [!TIP]
> To read the language reference offline at exactly your installed version, the `doc/langref.html.in` file lives inside your Zig installation. For API-level standard-library documentation, run `zig std` to browse it in your browser.

---

_Generated June 2026 from ziglang/zig at 738d2be. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
