# Appendix E. Build System Reference

### Appendix E. Build System Reference

Zig builds programs with Zig code. The build script is named:

```text
build.zig
```

Run it with:

```sh
zig build
```

A build script defines steps. A step may compile an executable, run tests, install an artifact, run a program, or perform another build action.

### E.1 Minimal Build Script

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

pub fn build(b: *std.Build) void {
    const exe = b.addExecutable(.{
        .name = "hello",
        .root_source_file = b.path("src/main.zig"),
        .target = b.standardTargetOptions(.{}),
        .optimize = b.standardOptimizeOption(.{}),
    });

    b.installArtifact(exe);
}
```

Project layout:

```text
hello/
    build.zig
    src/
        main.zig
```

Build:

```sh
zig build
```

Run the installed executable:

```sh
./zig-out/bin/hello
```

### E.2 The Build Function

Every build script exports a `build` function.

```zig
pub fn build(b: *std.Build) void {
    ...
}
```

The argument `b` is the build graph object. It creates compile steps, run steps, install steps, options, modules, and dependencies.

### E.3 Target and Optimize Options

Most build scripts begin with the standard target and optimization options.

```zig
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
```

Use them in artifacts:

```zig
const exe = b.addExecutable(.{
    .name = "app",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});
```

Then the user can choose:

```sh
zig build -Dtarget=x86_64-linux
zig build -Doptimize=ReleaseFast
```

Common optimize modes:

```text
Debug
ReleaseSafe
ReleaseFast
ReleaseSmall
```

### E.4 Executables

Create an executable:

```zig
const exe = b.addExecutable(.{
    .name = "app",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});
```

Install it:

```zig
b.installArtifact(exe);
```

Add imports or link libraries before installing.

### E.5 Libraries

Static library:

```zig
const lib = b.addStaticLibrary(.{
    .name = "mylib",
    .root_source_file = b.path("src/lib.zig"),
    .target = target,
    .optimize = optimize,
});
```

Shared library:

```zig
const lib = b.addSharedLibrary(.{
    .name = "mylib",
    .root_source_file = b.path("src/lib.zig"),
    .target = target,
    .optimize = optimize,
});
```

Install:

```zig
b.installArtifact(lib);
```

### E.6 Modules

A module is an importable unit of Zig code.

```zig
const mod = b.createModule(.{
    .root_source_file = b.path("src/lib.zig"),
    .target = target,
    .optimize = optimize,
});
```

Import it into an executable:

```zig
exe.root_module.addImport("mylib", mod);
```

Then in Zig code:

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

### E.7 Tests

Create a test artifact:

```zig
const tests = b.addTest(.{
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});
```

Create a run step for it:

```zig
const run_tests = b.addRunArtifact(tests);
```

Expose it as a named build step:

```zig
const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_tests.step);
```

Run:

```sh
zig build test
```

### E.8 Run Steps

Run an executable from the build graph.

```zig
const run_cmd = b.addRunArtifact(exe);
```

Make it depend on installation if needed:

```zig
run_cmd.step.dependOn(b.getInstallStep());
```

Expose it:

```zig
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
```

Run:

```sh
zig build run
```

Pass arguments after `--`.

```zig
if (b.args) |args| {
    run_cmd.addArgs(args);
}
```

Command:

```sh
zig build run -- input.txt output.txt
```

### E.9 Build Options

Define a boolean option:

```zig
const enable_log = b.option(
    bool,
    "log",
    "Enable logging",
) orelse false;
```

Create an options module:

```zig
const options = b.addOptions();
options.addOption(bool, "enable_log", enable_log);
```

Import it into the program:

```zig
exe.root_module.addOptions("build_options", options);
```

Use it:

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

if (build_options.enable_log) {
    // logging code
}
```

Command:

```sh
zig build -Dlog=true
```

### E.10 Dependencies

Fetch dependencies with `zig fetch`, then import them in `build.zig.zon`.

A build script reads a dependency by name.

```zig
const dep = b.dependency("example", .{
    .target = target,
    .optimize = optimize,
});
```

Import one of its modules:

```zig
exe.root_module.addImport(
    "example",
    dep.module("example"),
);
```

Then in source:

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

### E.11 Linking C

Link libc:

```zig
exe.linkLibC();
```

Add C source files:

```zig
exe.addCSourceFile(.{
    .file = b.path("src/add.c"),
    .flags = &.{ "-std=c99" },
});
```

Add include path:

```zig
exe.addIncludePath(b.path("include"));
```

Link a system library:

```zig
exe.linkSystemLibrary("m");
```

### E.12 Installing Files

Install an artifact:

```zig
b.installArtifact(exe);
```

Install a file:

```zig
b.installFile("README.md", "share/app/README.md");
```

Install a directory:

```zig
b.installDirectory(.{
    .source_dir = b.path("assets"),
    .install_dir = .prefix,
    .install_subdir = "share/app/assets",
});
```

### E.13 Custom Steps

Create a named step:

```zig
const docs = b.step("docs", "Build documentation");
```

Make it depend on another step:

```zig
docs.dependOn(&some_other_step.step);
```

A custom step is useful when a project has several tasks:

```sh
zig build test
zig build docs
zig build run
```

### E.14 Common Build Script

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

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    const tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_tests = b.addRunArtifact(tests);

    const test_step = b.step("test", "Run tests");
    test_step.dependOn(&run_tests.step);
}
```

This build script supports:

```sh
zig build
zig build run
zig build test
zig build -Doptimize=ReleaseFast
zig build -Dtarget=aarch64-linux
```

A Zig build script is an ordinary Zig program. Keep it plain. Create artifacts, connect steps, expose the few commands the project needs.

