# Zig Admin & Architecture Guide

This guide is for toolchain integrators, compiler contributors, platform engineers, and architects who need to understand **how the Zig compiler is built, how it processes source code, and how to deploy and operate it**. Where the [User Guide](/guides/ziglang/zig/user-guide/) covers driving the `zig` binary, this guide covers what is behind it: the compilation pipeline, the self-hosted code generators and linkers, the package manager, the bundled libc/C++ runtime, and the security model.

> [!NOTE]
> This guide documents Zig **0.16.0** (development series) at the referenced commit. The compiler is self-hosted (written in Zig) and pre-1.0; internal module layout and IR formats change between releases. File paths and module responsibilities here are taken directly from `src/` and `lib/` at this commit.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture](#2-system-architecture)
3. [The Compilation Pipeline](#3-the-compilation-pipeline)
4. [Repository Structure](#4-repository-structure)
5. [Core Compiler Modules](#5-core-compiler-modules)
6. [Code Generation Backends](#6-code-generation-backends)
7. [The Linkers](#7-the-linkers)
8. [The Build System & Package Manager](#8-the-build-system--package-manager)
9. [The Bundled C/C++ Runtime](#9-the-bundled-cc-runtime)
10. [Bootstrapping](#10-bootstrapping)
11. [Build & Deployment](#11-build--deployment)
12. [Caching & Incremental Compilation](#12-caching--incremental-compilation)
13. [The Compiler Server Protocol](#13-the-compiler-server-protocol)
14. [Configuration Reference](#14-configuration-reference)
15. [Security Analysis](#15-security-analysis)
16. [Operations](#16-operations)
17. [Code Quality & Conventions](#17-code-quality--conventions)
18. [Testing Strategy](#18-testing-strategy)
19. [Known Issues & Improvements](#19-known-issues--improvements)
20. [Quick Reference](#20-quick-reference)

---

## 1. Executive Summary

Zig is a **self-hosted compiler toolchain**: the Zig compiler is itself written in Zig (plus a small C bootstrap). One binary delivers a Zig compiler, a C/C++ compiler, a cross-compilation system, a build system, a package manager, and a code formatter.

| Attribute | Value |
|---|---|
| Language of implementation | Zig (self-hosted) + C bootstrap (`bootstrap.c`, `stage1/`) |
| Frontend IRs | AST → **ZIR** (untyped) → **AIR** (typed, analyzed) |
| Code generators | Self-hosted backends for x86-64, aarch64, arm, riscv64, sparc64, mips, wasm, spirv, C; plus an **LLVM** backend |
| Linkers | Self-hosted ELF, COFF, Mach-O, Wasm, SPIR-V, C; plus **LLD** fallback |
| Bundled runtime | musl, glibc stubs, wasi-libc, libc++, libc++abi, libunwind, compiler-rt, libtsan |
| Build dependency | LLVM/Clang/LLD (for the LLVM-enabled build); CMake + a C++ compiler for bootstrap |
| License | MIT (compiler); bundled third-party libc/runtime under their own licenses |
| Maturity | Pre-1.0, actively developed |

**Architectural thesis.** Zig deliberately *does not* depend on a system C toolchain. By vendoring libc sources and shipping its own backends and linkers, the toolchain is hermetic: any host can compile for any supported target with reproducible results and no external sysroot. The major engineering investments — `comptime` evaluation in `Sema`, the `InternPool` value/type store, the self-hosted backends, and the integrated build/package system — all serve that thesis.

> [!IMPORTANT]
> The largest single source file in the project is `src/Sema.zig` (~1.6 MB). It is the semantic-analysis engine *and* the compile-time interpreter — `comptime` code execution, type checking, generic instantiation, and AIR generation all live there. Any change to language semantics touches this file. Treat it as the architectural center of gravity.

---

## 2. System Architecture

```
                        ┌─────────────────────────────────────────────┐
                        │                 zig (one binary)             │
                        └─────────────────────────────────────────────┘
                                            │
        ┌───────────────┬───────────────────┼───────────────────┬───────────────┐
        ▼               ▼                   ▼                   ▼               ▼
   CLI dispatch    Zig frontend       C/C++ frontend       Build runner    Drop-in tools
   (src/main.zig)  (lib/std/zig +     (bundled Clang)      (lib/compiler/  (cc/c++/ar/
                    src/Sema, AIR)                          build_runner)   ranlib/objcopy…)
        │               │                   │                   │
        │               ▼                   │                   │
        │     ┌──────────────────┐          │                   │
        │     │  Sema + InternPool│          │                   │
        │     │  (src/Sema.zig,   │          │                   │
        │     │   src/InternPool, │          │                   │
        │     │   src/Zcu.zig)    │          │                   │
        │     └────────┬─────────┘           │                   │
        │              ▼ AIR                  ▼                   ▼
        │     ┌──────────────────────────────────────────────────────┐
        │     │             Code generation (src/codegen/)            │
        │     │  x86_64 · aarch64 · arm · riscv64 · sparc64 · mips ·  │
        │     │  wasm · spirv · c   +   LLVM backend (src/codegen/llvm)│
        │     └────────────────────────┬─────────────────────────────┘
        │                              ▼
        │     ┌──────────────────────────────────────────────────────┐
        │     │                 Linkers (src/link/)                   │
        │     │  Elf · Coff · MachO · Wasm · SpirV · C  + LLD (Lld.zig)│
        │     └────────────────────────┬─────────────────────────────┘
        │                              ▼
        └────────────────────────►  Output artifact (exe / lib / obj / wasm / C)
```

The compiler is orchestrated by `src/Compilation.zig`, which owns the whole-program state: the set of modules, the C objects to compile, the link task, and the on-disk cache. A `Compilation` drives the frontend per module and then hands typed IR (AIR) to a backend and the result to a linker.

---

## 3. The Compilation Pipeline

Zig source flows through a fixed sequence of intermediate representations. The frontend (tokenize → parse → AstGen → Sema) lives mostly in `lib/std/zig/`; semantic analysis and everything typed lives in `src/`.

```
 source.zig
    │  tokenizer.zig
    ▼
 Tokens
    │  Parse.zig → Ast.zig
    ▼
 AST (Abstract Syntax Tree)
    │  AstGen.zig   (+ AstRlAnnotate.zig result-location pass)
    ▼
 ZIR  (Zig Intermediate Representation — untyped, per-file, cacheable)   ← Zir.zig
    │  Sema.zig     (semantic analysis + comptime interpreter; uses InternPool + Zcu)
    ▼
 AIR  (Analyzed IR — fully typed, monomorphized)                         ← Air.zig
    │  src/codegen/<backend>
    ▼
 Machine code / object / C / wasm
    │  src/link/<format>
    ▼
 Linked artifact
```

### 3.1 Stage responsibilities

| Stage | Module | Output | Notes |
|---|---|---|---|
| Tokenize | `lib/std/zig/tokenizer.zig` | Token stream | Shared with `zig fmt`, tooling |
| Parse | `lib/std/zig/Parse.zig`, `Ast.zig` | AST | Also drives `zig fmt` reformatting |
| AstGen | `lib/std/zig/AstGen.zig` | **ZIR** | Untyped, position-independent, per-file; cached |
| Result-location annotate | `lib/std/zig/AstRlAnnotate.zig` | annotations | Computes where results are stored (RLS) |
| Semantic analysis | `src/Sema.zig` | **AIR** | Type checking, `comptime` execution, generic instantiation, error/optional handling |
| Codegen | `src/codegen/*` | object/asm/C/wasm | One backend per architecture + LLVM |
| Link | `src/link/*` | final artifact | One linker per object format + LLD |

### 3.2 ZIR vs AIR

- **ZIR** (`Zir.zig`) is *untyped* and produced per source file by `AstGen`. It is independent of how the file is used, so it is a natural caching boundary and the basis for incremental compilation. The `changelist`/`dump-zir` debug commands operate on ZIR.
- **AIR** (`Air.zig`) is *fully typed and monomorphized* — generics are expanded, `comptime` is resolved, and every instruction has a concrete type. Backends consume AIR. `--verbose-air` dumps it.
- **ZOIR / ZON** (`Zoir.zig`, `ZonGen.zig`) is the parallel path for **Zig Object Notation** (`build.zig.zon`, `.zon` data files), which is parsed but not executed.

> [!NOTE]
> Because ZIR is untyped and cached per file, editing one file invalidates only that file's ZIR; `Sema` then re-analyzes downstream. This is the foundation of `-fincremental`. The `InternPool` makes re-analysis cheap by deduplicating already-seen types and values.

---

## 4. Repository Structure

The repository is dominated by **vendored third-party C/C++ sources** (libc, libc++, runtime). The Zig compiler itself is a relatively small share of the 20,000+ files. Knowing the split is essential to navigating the tree.

| Path | Role | Owned by Zig? |
|---|---|---|
| `src/` | The self-hosted compiler (frontend types, Sema, AIR, codegen, link, CLI) | **Yes** — core |
| `lib/std/` | The Zig standard library | **Yes** — core |
| `lib/std/zig/` | Tokenizer, parser, AstGen, ZIR, the build DSL surface | **Yes** — core |
| `lib/compiler/` | Build runner, `translate-c`, `resinator` (rc), `aro` (C parser), `objcopy`, `libc`, std-docs server | **Yes** — core |
| `lib/init/` | Templates emitted by `zig init` | **Yes** |
| `lib/compiler_rt/` | Compiler runtime (software floats, builtins) — Zig reimplementation | **Yes** (292 files) |
| `lib/docs/` | The standard-library docs web app (WASM) | **Yes** |
| `lib/libc/` | Vendored libc: musl, glibc stubs, wasi-libc, plus headers | Vendored |
| `lib/libcxx/`, `lib/libcxxabi/` | Vendored LLVM libc++ / libc++abi | Vendored |
| `lib/libunwind/` | Vendored LLVM libunwind | Vendored |
| `lib/libtsan/` | Vendored Thread Sanitizer runtime | Vendored |
| `lib/include/` | Bundled C headers (209 files) | Vendored/generated |
| `stage1/` | C bootstrap artifacts | Bootstrap |
| `bootstrap.c` | Minimal C bootstrap entry | Bootstrap |
| `doc/langref.html.in` | The Language Reference (canonical) | **Yes** |
| `doc/langref/` | Language-reference code examples (288 files) | **Yes** |
| `test/` | Behavior, link, standalone, CLI, cases test suites | **Yes** |
| `tools/` | Maintenance tools (glibc/spirv/crc updaters) | **Yes** |
| `ci/` | CI scripts (18 files) | **Yes** |
| `CMakeLists.txt` | Bootstrap build orchestration | **Yes** |
| `build.zig` | The compiler's own Zig build script | **Yes** |

> [!TIP]
> When reading this repo, mentally subtract `lib/libc/**`, `lib/libcxx/**`, `lib/libcxxabi/**`, `lib/libunwind/**`, and `lib/libtsan/**` — those are upstream C/C++ projects vendored so the toolchain is hermetic. The *compiler* you actually maintain is `src/` + `lib/std/` + `lib/compiler/`.

---

## 5. Core Compiler Modules

The `src/` directory, sorted by size, reveals where the complexity lives:

| Module | ~Size | Responsibility |
|---|---|---|
| `src/Sema.zig` | 1.6 MB | Semantic analysis + `comptime` interpreter; emits AIR |
| `src/InternPool.zig` | 512 KB | Deduplicated, interned store of all types and values |
| `src/main.zig` | 350 KB | CLI entry point, argument parsing, command dispatch |
| `src/Compilation.zig` | 344 KB | Whole-program orchestration, C-object compilation, cache |
| `src/Zcu.zig` | 212 KB | "Zig Compilation Unit" — module graph, declarations, incremental state |
| `src/clang_options_data.zig` | 181 KB | Clang command-line option tables (for `zig cc`) |
| `src/Type.zig` | 165 KB | The `Type` representation and operations |
| `src/Value.zig` | 135 KB | The compile-time `Value` representation |
| `src/print_zir.zig` | 121 KB | ZIR pretty-printer (debug) |
| `src/Air.zig` | 104 KB | Analyzed IR definition |
| `src/link.zig` | 93 KB | Linker dispatch and shared link logic |
| `src/codegen.zig` | 52 KB | Codegen dispatch shared across backends |
| `src/target.zig` | 28 KB | Target capabilities, backend selection |
| `src/register_manager.zig` | 28 KB | Register allocation helper for self-hosted backends |
| `src/Builtin.zig` | 13 KB | `@import("builtin")` generation |
| `src/Package.zig` + `src/Package/` | — | Package manager: manifest, fetch, hashing |

Supporting subdirectories: `src/Sema/`, `src/Zcu/`, `src/Air/`, `src/Compilation/`, and `src/codegen/`, `src/link/`, `src/Package/`, `src/libs/`.

### 5.1 InternPool — the value/type store

`InternPool` is the canonical, deduplicated database of every type and comptime value the compiler has seen. Interning means structural equality becomes pointer (index) equality, which makes type comparison, generic-instance deduplication, and incremental re-analysis fast and memory-efficient. `--verbose-intern-pool` dumps its activity.

### 5.2 Zcu — the compilation unit

`Zcu` (Zig Compilation Unit, formerly "Module") tracks the graph of Zig modules, their declarations, dependency edges between declarations, and the incremental state needed to recompile only what changed. It is the bookkeeping layer that sits between `Compilation` (whole program) and `Sema` (per-declaration analysis).

### 5.3 Sema — semantics and comptime

`Sema` walks ZIR and produces AIR. It is simultaneously the type checker, the generic-function instantiator, and the **compile-time interpreter** that executes `comptime` code. This is why it is by far the largest file: Zig's metaprogramming model (types as comptime values, `comptime` blocks, `inline` loops, generic functions parameterized by `type`) is all evaluated here rather than via a separate macro system.

---

## 6. Code Generation Backends

A distinctive Zig design choice: the compiler ships **its own code generators**, not just an LLVM binding. `src/codegen/` contains:

| Backend | Path | Status / role |
|---|---|---|
| x86-64 | `src/codegen/x86_64/` | Self-hosted; the flagship native backend |
| aarch64 | `src/codegen/aarch64/` | Self-hosted |
| arm | `src/codegen/arm/` | Self-hosted (32-bit ARM) |
| riscv64 | `src/codegen/riscv64/` | Self-hosted |
| sparc64 | `src/codegen/sparc64/` | Self-hosted |
| mips | `src/codegen/mips/` | Self-hosted |
| wasm | `src/codegen/wasm/` | Self-hosted WebAssembly |
| spirv | `src/codegen/spirv/` | Self-hosted SPIR-V (GPU) |
| C | `src/codegen/c.zig` | Emits portable C source (`-ofmt=c`) |
| LLVM | `src/codegen/llvm.zig`, `src/codegen/llvm/` | LLVM IR backend (`-fllvm`) |

`src/target.zig` decides which backend to use. `selfHostedBackendIsAsRobustAsLlvm()` enumerates the targets where the self-hosted backend is considered production-ready; `zigBackend()` returns `stage2_llvm` when `use_llvm` is set, otherwise the architecture-specific self-hosted backend.

> [!IMPORTANT]
> The self-hosted backends do **not** require LLVM, which is why a standalone (no-LLVM) Zig build can still compile Zig programs. LLVM is required for: compiling C/C++ (`zig cc`), LTO, LLVM IR/bitcode emit, and any target where the self-hosted backend is not yet robust. `-fllvm` / `-fno-llvm` force the choice; `-flibllvm` / `-fno-libllvm` control whether the LLVM *API* (vs. textual IR) is used.

The self-hosted backends share infrastructure: `src/register_manager.zig` handles register allocation, and `src/codegen.zig` provides dispatch and common lowering. Debug output is available via `--verbose-air`, `--verbose-llvm-ir`, `--verbose-llvm-bc`, and `--verbose-generic-instances`.

---

## 7. The Linkers

Like codegen, Zig ships **its own linkers** so it does not depend on a host linker for supported formats (`src/link/`):

| Linker | Path | Format |
|---|---|---|
| ELF | `src/link/Elf.zig`, `src/link/Elf/`, `Elf2.zig` | ELF (Linux, BSD) |
| COFF | `src/link/Coff.zig` | COFF/PE (Windows) |
| Mach-O | `src/link/MachO.zig`, `src/link/MachO/` | Mach-O (macOS, iOS) |
| Wasm | `src/link/Wasm.zig`, `src/link/Wasm/` | WebAssembly |
| SPIR-V | `src/link/SpirV.zig`, `src/link/SpirV/` | SPIR-V (GPU) |
| C | `src/link/C.zig` | C source aggregation |
| LLD | `src/link/Lld.zig` | Fallback to bundled LLD |

Supporting pieces: `Dwarf.zig` (debug info), `LdScript.zig` (GNU linker-script parsing), `StringTable.zig`, `MappedFile.zig`, `Queue.zig` (incremental link task queue), and `tapi/` (Apple text-based dylib `.tbd` parsing).

`-flld` / `-fno-lld` force or prevent LLD. `--debug-link-snapshot` dumps the linker's internal state as JSON for debugging incremental linking.

> [!NOTE]
> Self-hosted linking enables fast incremental linking and removes the external `ld`/`lld` dependency for the common formats. LLD remains available (and is the default for some configurations) via the vendored sources in `src/libs/`.

---

## 8. The Build System & Package Manager

### 8.1 Build system layers

```
build.zig  (user-written, pub fn build(b: *std.Build))
    │  describes a graph of std.Build.Step
    ▼
build_runner.zig  (lib/compiler/build_runner.zig)
    │  parses CLI, resolves the graph, executes steps in parallel, caches
    ▼
zig build subprocess(es)  (compile/link each artifact)
```

`std.Build` (`lib/std/Build.zig` and submodules) is the DSL: `addExecutable`, `addModule`, `addLibrary`, `addTest`, `installArtifact`, `step`, `dependency`, `option`, `standardTargetOptions`, `standardOptimizeOption`. The build script *constructs* the graph; the **build runner** (`lib/compiler/build_runner.zig`) executes it. The runner is what implements `--watch`, `--summary`, `--fuzz`, `--webui`, `--time-report`, `-j`, `--maxrss`, and the system-integration flags.

### 8.2 Package manager

`src/Package/` and `src/Package.zig` implement the package manager:

- **Manifest** — `build.zig.zon` is parsed via the ZON path (`Zoir.zig`/`ZonGen.zig`). Fields: `name`, `version`, `fingerprint`, `minimum_zig_version`, `dependencies`, `paths`.
- **Fetch** — `zig fetch` resolves `git+http(s)`, tarball, git-bundle, and local-path sources; downloads into the global cache; computes a content hash over the declared `paths`.
- **Content addressing** — packages are keyed by hash, so a given version is stored once in the global cache and shared across projects. Lazy dependencies are fetched on demand (`--fetch=needed`) or eagerly (`--fetch=all`).
- **Fingerprint** — a 64-bit (32-bit id + 32-bit checksum) globally-unique identity, auto-generated and immutable, used to detect that two packages are versions of the same project.

> [!CAUTION]
> The fingerprint is a supply-chain identity primitive. Copying another package's fingerprint into a fork is treated by the toolchain as a **hostile** attempt to impersonate the upstream package. Tooling and downstream consumers rely on fingerprint stability; never regenerate it except when intentionally forking an abandoned project.

---

## 9. The Bundled C/C++ Runtime

To make `zig cc` and cross-compilation hermetic, Zig vendors a complete C/C++ runtime:

| Component | Path | Purpose |
|---|---|---|
| musl | `lib/libc/musl/` | musl libc source (built on demand per target) |
| glibc stubs | `lib/libc/glibc/` | Version-stubbed glibc for compile-time linking |
| wasi-libc | `lib/libc/wasi/` | libc for WebAssembly/WASI |
| Generic headers | `lib/libc/include/`, `lib/include/` | Multi-target C headers |
| libc++ | `lib/libcxx/` | LLVM C++ standard library |
| libc++abi | `lib/libcxxabi/` | C++ ABI support |
| libunwind | `lib/libunwind/` | Stack unwinding for exceptions |
| compiler-rt | `lib/compiler_rt/` | Software builtins (Zig reimplementation, 292 files) |
| libtsan | `lib/libtsan/` | ThreadSanitizer runtime |

### 9.1 glibc handling (`lib/libc/glibc/README.md`)

Zig does not ship glibc binaries. It ships an `abilist` blob describing which symbols each glibc version exports, and `src/glibc.zig` parses it to synthesize **stub shared objects** on demand. These stubs are used only for compile-time linking — the real glibc on the target machine provides implementations at run time.

- Supported glibc range: **2.17+** (2012) for Zig programs (the std library needs 2.17 symbols), **2.2.5+** for pure `zig cc` usage.
- Public glibc headers live in `lib/libc/include/generic-glibc/` with Zig-specific `#ifdef`s so one header set represents every supported version.
- Invisible CRT objects (`crti.o`, `crtn.o`, `Scrt1.o`, `libc_nonshared.a`) are also vendored and statically linked.

> [!IMPORTANT]
> The vendored libc/libc++/libunwind directories carry their **own upstream licenses** (musl=MIT, wasi-libc multi-licensed Apache-2.0-with-LLVM-exceptions/Apache-2.0/MIT, cloudlibc=BSD-2-Clause, etc.). When redistributing a Zig toolchain, preserve those license files. The Zig compiler itself is MIT-licensed.

---

## 10. Bootstrapping

Because the compiler is written in Zig, building it from source requires either an existing Zig binary or a bootstrap path. The repository supports both:

- **`bootstrap.c` + `stage1/`** — a minimal C bootstrap that builds a first working `zig`.
- **`CMakeLists.txt`** (31 KB) — orchestrates the full from-source build, including the bundled LLVM/Clang/LLD linkage for the LLVM-enabled toolchain.
- **`build.zig`** — once a `zig` exists, the compiler builds itself with its own build system. `build.zig` defines `zig_version` (currently `0.16.0`) and the version-string logic (tagged release vs `-dev.NNNN+hash` untagged build derived from git).

The general flow:

```
bootstrap.c / existing zig
        │  (CMake for the LLVM-enabled build)
        ▼
   stage1 zig
        │  build.zig
        ▼
   stage2 zig  (self-compiled, the shipped compiler)
```

> [!NOTE]
> The `-dev.NNNN+hash` version suffix is computed in `build.zig` from the git history relative to the most recent tagged ancestor; `build.zig` enforces that `zig_version` must be greater than the tagged ancestor it derives from.

---

## 11. Build & Deployment

### 11.1 Building the toolchain from source

| Requirement | Detail |
|---|---|
| CMake | Drives the bootstrap and LLVM linkage |
| C++ compiler | To compile the bootstrap and link LLVM |
| LLVM / Clang / LLD | For the LLVM-enabled (official) build; matched to the version Zig pins |
| An existing `zig` | Optional shortcut to skip the C bootstrap |

The CI scripts in `ci/` (18 files) encode the canonical per-platform build, test, and release procedures — consult them for the exact, version-pinned LLVM and build invocations rather than reconstructing them by hand.

### 11.2 Deploying / distributing Zig

Zig is deployed by **copying the `zig` binary together with its `lib/` directory**. There is no installer and no system integration required. Deployment options:

- **Per-user**: unpack the release archive anywhere and add it to `PATH`.
- **System-wide**: place under `/opt/zig` (or similar) and symlink `zig` onto `PATH`.
- **CI**: cache the release tarball; pin a version. `zig env` confirms the resolved paths.

> [!TIP]
> For reproducible CI, pin the exact Zig version, set `--global-cache-dir` to a cached location so fetched packages persist between runs, and pre-fetch dependencies with `zig build --fetch=all`. Because the toolchain is hermetic, the same Zig version produces the same artifacts regardless of host.

### 11.3 Relocation

If the binary must be separated from `lib/`, point it back with `--zig-lib-dir [path]` or the `ZIG_LIB_DIR` environment variable. The directory layout is reported by `zig env` (`lib_dir`, `std_dir`).

---

## 12. Caching & Incremental Compilation

Zig's caching operates at multiple granularities:

- **ZIR cache** — per-file untyped IR is cached; unchanged files skip AstGen.
- **Local cache** (`--cache-dir`, default `.zig-cache/`) — per-project build artifacts and intermediate objects.
- **Global cache** (`--global-cache-dir`, see `zig env`) — fetched packages (content-addressed) and shared artifacts.
- **Incremental compilation** (`-fincremental` / `-fno-incremental`) — re-analyzes only declarations affected by a change, leveraging `Zcu`'s dependency graph and the `InternPool`.

Debug aids: `--debug-incremental` enables incremental debug features; `src/IncrementalDebugServer.zig` exposes incremental state; `--debug-link-snapshot` dumps linker state.

> [!NOTE]
> The cache is keyed on a hash of all inputs (source, flags, target, compiler version). Changing the Zig version invalidates the cache, which is correct: different compiler versions can produce different output for identical source.

---

## 13. The Compiler Server Protocol

The compiler can run as a long-lived server that streams results to a client, used by the build system and by IDE tooling. The protocol is defined in `lib/std/zig/Server.zig` and `lib/std/zig/Client.zig`.

- Activated by `--listen` (clients connect and receive incremental updates, error bundles, and progress).
- `--time-report` sends per-file timing diagnostics to `--listen` clients.
- This is what powers `zig build --watch`, the `--webui` interface, and integration with language servers.
- The community feature request to "implement a server in the compiler that serves information about the compilation" (issue [#615](https://github.com/ziglang/zig/issues/615)) tracks the broader direction here.

---

## 14. Configuration Reference

Zig has no configuration files for the compiler itself — behavior is controlled entirely by command-line flags and a small set of environment variables. The full flag set is in the [User Guide reference](/guides/ziglang/zig/user-guide/); the integrator-relevant subset:

### 14.1 Environment variables

| Variable | Effect |
|---|---|
| `ZIG_LIB_DIR` | Override the path to the Zig `lib/` directory |
| `ZIG_GLOBAL_CACHE_DIR` | Override the global cache directory |
| `ZIG_LOCAL_CACHE_DIR` | Override the local cache directory |
| `NO_COLOR` / `CLICOLOR_FORCE` | Standard color-control conventions honored by error output |

(Resolved values are reported in the `env` object of `zig env`.)

### 14.2 Backend / toolchain selection flags

| Flag | Effect |
|---|---|
| `-fllvm` / `-fno-llvm` | Force/prevent the LLVM codegen backend |
| `-flibllvm` / `-fno-libllvm` | Use the LLVM API vs. textual IR |
| `-fclang` / `-fno-clang` | Force/prevent Clang for C/C++ |
| `-flld` / `-fno-lld` | Force/prevent LLD as the linker |
| `-fcompiler-rt` / `-fno-compiler-rt` | Include/exclude compiler-rt symbols |
| `-fubsan-rt` / `-fno-ubsan-rt` | Include/exclude UBSan runtime |
| `-fincremental` / `-fno-incremental` | Incremental compilation |

### 14.3 Compiler-development debug flags

| Flag | Effect |
|---|---|
| `--verbose-air` | Dump AIR |
| `--verbose-intern-pool` | Dump InternPool activity |
| `--verbose-generic-instances` | Dump generic instantiation |
| `--verbose-llvm-ir[=path]` / `--verbose-llvm-bc=[path]` | Dump LLVM IR/BC |
| `--verbose-cimport` | Debug C imports |
| `--verbose-link` / `--verbose-cc` | Linker / C-compiler invocations |
| `--debug-log [scope]` | Scoped debug logging |
| `--debug-compile-errors` | Crash with diagnostics at the first compile error |
| `--debug-link-snapshot` | Dump linker state as JSON |
| `--debug-rt` | Debug compiler runtime libraries |
| `--debug-incremental` | Incremental compilation debug features |

---

## 15. Security Analysis

### 15.1 Language-level safety

Zig's primary security posture is **runtime safety checks** inserted in `Debug` and `ReleaseSafe` modes: integer overflow, out-of-bounds indexing, invalid pointer casts, null-unwrap, and `unreachable` all become defined panics rather than exploitable undefined behavior. `ReleaseFast`/`ReleaseSmall` remove these checks for performance — a deliberate, documented trade-off.

Additional hardening flags available per module: `-fstack-protector`, `-fstack-check`, `-fPIE`/`-fPIC`, `-fsanitize-c` (C UB detection), `-fsanitize-thread` (TSan), `-funwind-tables`, and `--build-id`.

### 15.2 Supply-chain security (packages)

- Dependencies in `build.zig.zon` carry a **content hash**; `zig fetch` verifies the downloaded content against it. A hash mismatch fails the fetch.
- Packages are **content-addressed** in the global cache, so a tampered re-download cannot silently replace a verified package.
- The **fingerprint** primitive defends package *identity*: it lets the toolchain detect when one package claims to be an updated version of another, and flags fork-impersonation.
- Lazy dependencies are only fetched when actually needed, reducing the attack surface of the dependency tree.

> [!WARNING]
> The hash in `build.zig.zon` is the trust anchor for a dependency. Treat `build.zig.zon` as security-sensitive: review hash changes in code review, pin to specific commits/tarballs, and run `zig build --fetch=all` in a controlled environment to populate the cache before building.

### 15.3 The bundled toolchain as attack surface

Because Zig vendors libc, libc++, libunwind, and an LLD/Clang frontend, the toolchain inherits the security posture of those upstream projects. Operators distributing Zig should track upstream CVEs for the vendored versions and update via the `tools/update_*` maintenance scripts.

### 15.4 What does *not* exist

To prevent fabricated expectations:

- There is **no network access during normal compilation** — only `zig fetch` / `zig build` (when dependencies are declared) touch the network.
- There is **no telemetry or phone-home** in the compiler.
- There is **no plugin/extension loading** of arbitrary native code into the compiler; `build.zig` is Zig code the build runner executes, but it is your own project's code, compiled by Zig.

---

## 16. Operations

### 16.1 Health checks

| Check | Command | Healthy result |
|---|---|---|
| Toolchain present | `zig version` | Prints a version string |
| Paths resolved | `zig env` | `lib_dir`/`std_dir` exist and match the binary |
| Can compile | `zig build-exe` of a hello-world | Produces a runnable binary |
| Can cross-compile | `zig build-exe hello.zig -target aarch64-linux-musl` | Produces an ELF for the target |
| Targets available | `zig targets` | Emits the full target JSON |

### 16.2 Diagnostics and logs

- Increase compile-error detail: `-freference-trace[=num]`.
- Trace linker/CC invocations: `--verbose-link`, `--verbose-cc`.
- Scoped logging: `--debug-log [scope]`.
- For compiler crashes, `src/crash_report.zig` produces a crash report; minimize the reproducer with `zig reduce` before filing.

### 16.3 Cache maintenance

The local cache lives in `.zig-cache/` per project; the global cache is reported by `zig env`. Both are safe to delete to force a clean rebuild; they will be repopulated. In CI, persist the **global** cache to avoid re-fetching packages, but treat the **local** cache as disposable.

### 16.4 Performance tuning

| Lever | Flag |
|---|---|
| Parallelism | `-j<N>` (compile) / `zig build -j<N>` |
| Memory cap | `zig build --maxrss <bytes>`, `--skip-oom-steps` |
| Incremental | `-fincremental` |
| Fewer LLVM passes (debugging) | `-fopt-bisect-limit=[n]` |
| Stack diagnostics | `-fstack-report` |
| Time report | `zig build --time-report` (per-file timings in the web UI) |

---

## 17. Code Quality & Conventions

- **Self-hosting** — the compiler is written in Zig and compiles itself; `zig fmt` enforces a single canonical style across the codebase with no configuration.
- **One IR per concern** — the strict AST → ZIR → AIR layering keeps untyped, typed, and lowered concerns separate and independently cacheable.
- **Interning over copying** — `InternPool` centralizes type/value identity, a pervasive convention that downstream code relies on for cheap equality.
- **Explicit allocators** — consistent with the standard library, compiler data structures take allocators explicitly; there is no hidden global allocation.
- **Vendoring over dependencies** — third-party C/C++ runtime is vendored (not fetched at build time) to keep the toolchain hermetic and reproducible.
- **Debug dumpers as first-class** — `print_zir.zig`, `print_air.zig` (via `Air`), `print_value.zig`, `print_zoir.zig`, `print_targets.zig`, `print_env.zig` give every IR a human-readable form, reflecting a debugging-forward culture.

---

## 18. Testing Strategy

The `test/` tree is extensive and structured by concern:

| Suite | Path | Purpose |
|---|---|---|
| Behavior tests | `test/behavior/` (116 files) | Language-feature correctness (the core regression suite) |
| Compile-error cases | `test/cases/` (59 files) | Assert exact compile-error output |
| Link tests | `test/link/` | Linker correctness across formats |
| Standalone tests | `test/standalone/` | Whole-program scenarios (entry points, env vars, child processes, Windows argv, etc.) |
| CLI tests | `test/cli/` | Command-line behavior |
| C ABI tests | `test/c_abi/` | C interop ABI conformance |
| Incremental tests | `test/incremental/` | Incremental-compilation correctness |

Tests are driven through the compiler's own build system (`zig build test`, `test-standalone`, etc.). Many standalone tests (e.g. `test/standalone/windows_argv/`) are themselves fuzz harnesses with `-Diterations` / `-Dseed` options. The combination of behavior tests + exact-output compile-error cases is the project's primary guard against language regressions.

> [!TIP]
> When contributing, the fast inner loop is `zig build test-behavior --test-filter <name>`. Compile-error cases under `test/cases/` assert the *exact* error text, so changing a diagnostic message requires updating the corresponding case.

---

## 19. Known Issues & Improvements

These are drawn from the project's open issue tracker and represent real, community-reported work items — useful context for integrators assessing maturity.

### 19.1 Backend / codegen

- LLVM lowering bugs on specific targets: MIPS r6 `j $ra` misassembly ([#21315](https://github.com/ziglang/zig/issues/21315)), `f128` vectors / `@reduce` builtins ([#24638](https://github.com/ziglang/zig/issues/24638)), WASM `atan2` LLVM crash ([#20641](https://github.com/ziglang/zig/issues/20641)), PPC inline-asm with `crX` registers ([#9208](https://github.com/ziglang/zig/issues/9208)).
- Self-hosted x86-64 backend edge cases historically surface as `genSetReg`/`emit MIR failed` assertions ([#24181](https://github.com/ziglang/zig/issues/24181), [#23279](https://github.com/ziglang/zig/issues/23279)) — expected churn for a young backend.
- `x86_64-linux-muslx32` cannot yet build LLVM ([#25374](https://github.com/ziglang/zig/issues/25374)); an `x32` triple environment patch to LLVM is proposed ([#25649](https://github.com/ziglang/zig/issues/25649)).

### 19.2 C interop / `zig cc`

- Nested `@` response files are unsupported (`NestedResponseFile`, [#24386](https://github.com/ziglang/zig/issues/24386)).
- Historical Windows multi-`@cImport` slowness/hangs ([#4568](https://github.com/ziglang/zig/issues/4568)) and macOS `stat`/`cImport` differences ([#14790](https://github.com/ziglang/zig/issues/14790)).

### 19.3 Platform coverage

- Darwin `kevent64_s` definitions drifted ([#21200](https://github.com/ziglang/zig/issues/21200)).
- UEFI regresses due to lack of CI build coverage ([#22809](https://github.com/ziglang/zig/issues/22809)) — a CI-coverage gap, not a code defect.

### 19.4 Language / diagnostics proposals

- Better error when switching on a pointer instead of a tagged union ([#13856](https://github.com/ziglang/zig/issues/13856)).
- Terminology shift to "detectable illegal behavior" over "safety-checked undefined behavior" ([#2402](https://github.com/ziglang/zig/issues/2402)).
- Remove redundant `cpu`/`os`/`abi`/`object_format` decls from `@import("builtin")` ([#22267](https://github.com/ziglang/zig/issues/22267)).

> [!NOTE]
> The density of LLVM-lowering issues vs. self-hosted-backend issues reflects the in-progress migration toward the self-hosted backends as the default. For maximum stability today, integrators targeting mainstream platforms should test both `-fllvm` and the default backend and pin a known-good Zig version.

---

## 20. Quick Reference

### 20.1 Module map (where to look)

| I want to change… | Look in |
|---|---|
| A CLI command or flag | `src/main.zig` (and `lib/compiler/*` for `cc`/`objcopy`/`libc`/`rc`) |
| Tokenizer / parser / formatter | `lib/std/zig/{tokenizer,Parse,Ast}.zig`, `src/fmt.zig` |
| Untyped IR generation | `lib/std/zig/AstGen.zig`, `Zir.zig` |
| Type checking / comptime / generics | `src/Sema.zig` (+ `src/Sema/`) |
| Type/value representation | `src/Type.zig`, `src/Value.zig`, `src/InternPool.zig` |
| Module graph / incremental | `src/Zcu.zig` (+ `src/Zcu/`) |
| Whole-program orchestration | `src/Compilation.zig` |
| A codegen backend | `src/codegen/<arch>/` |
| A linker | `src/link/<Format>.zig` |
| The build DSL | `lib/std/Build.zig` |
| The build runner | `lib/compiler/build_runner.zig` |
| The package manager | `src/Package/`, `src/Package.zig` |
| `@import("builtin")` | `src/Builtin.zig` |

### 20.2 Pipeline at a glance

```
source → tokenizer → Ast → AstGen → ZIR → Sema(+InternPool,Zcu) → AIR → codegen → link → artifact
```

### 20.3 Key debug switches

```
--verbose-air   --verbose-intern-pool   --verbose-llvm-ir   --verbose-link
--debug-log <scope>   --debug-incremental   --debug-link-snapshot   -freference-trace
```

### 20.4 Backend & linker matrix

| | Self-hosted | LLVM/LLD |
|---|---|---|
| **Codegen** | x86_64, aarch64, arm, riscv64, sparc64, mips, wasm, spirv, C | `-fllvm` |
| **Link** | ELF, COFF, Mach-O, Wasm, SPIR-V, C | `-flld` |

---

_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._
