# build.zig: Builds as Zig Code — Zig

Source: https://www.geekswithgeeks.com/en/zig/b-build

> Define executables, libraries, steps and options in build.zig.

## No Make, no CMake: just Zig

A Zig project's build is described by **`build.zig`**, a Zig program whose `build` function receives a `*std.Build` and declares a **graph of steps**. You create **modules** (`b.createModule` with a root source file, target and optimisation mode), then **artifacts**: `b.addExecutable`, `b.addLibrary` (static or dynamic) and `b.addTest`. `b.installArtifact` copies outputs to `zig-out/`. **Steps** (`b.step("run", ...)`) appear as commands: `zig build run`, `zig build test`. `b.standardTargetOptions` and `b.standardOptimizeOption` add the `-Dtarget` and `-Doptimize` flags, and **`b.option`** defines custom options (`-Dwith-metrics=true`) that can be passed to code through **build options** modules. Builds are **cached** and parallel, and steps can run arbitrary tools, generate code, or compile C sources (`addCSourceFiles`). Because it is real code, conditional logic and reuse are easy, and the same build works on every platform without external tools. The build API changes between releases (for example, executables now take a `root_module`), so start from the template `zig init` produces for your version.

## The build graph

build.zig declares steps; zig build runs the ones you ask for, in dependency order.

![A small directed graph of boxes: compile module, executable, install, run and test, with arrows showing dependencies.](assets/figures/zig/section-7-map.svg) — Figure 7.1 — Steps and dependencies in build.zig.

## A build.zig with run and test steps

Zig 0.15-style build script with a custom option.

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

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const enable_metrics = b.option(bool, "metrics", "Enable metrics collection") orelse false;

    const options = b.addOptions();
    options.addOption(bool, "enable_metrics", enable_metrics);

    const exe_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    exe_module.addOptions("build_options", options);   // @import("build_options") in code

    const exe = b.addExecutable(.{
        .name = "invoices",
        .root_module = exe_module,
    });
    b.installArtifact(exe);                             // zig-out/bin/invoices

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    if (b.args) |args| run_cmd.addArgs(args);           // zig build run -- --month 9
    const run_step = b.step("run", "Run the invoice tool");
    run_step.dependOn(&run_cmd.step);

    const unit_tests = b.addTest(.{ .root_module = exe_module });
    const run_tests = b.addRunArtifact(unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_tests.step);
}

// zig build -Dmetrics=true -Doptimize=ReleaseSafe
// in src/main.zig:  const build_options = @import("build_options");
//                   if (build_options.enable_metrics) { ... }
```

## Regenerate the template after upgrading

When moving to a new Zig version, compare your build.zig with a fresh `zig init` template. Build API changes are the most common upgrade breakage, and the template shows the current idioms.

**Quiz:** What is build.zig?

- [x] A Zig program that declares the build graph using std.Build
- [ ] A configuration file in YAML
- [ ] A Makefile
- [ ] A list of compiler flags

*Answer:* A Zig program that declares the build graph using std.Build. Builds are written in Zig itself, so they are portable and programmable.
