Skip to main content
Zig’s package management is decentralized and integrated into the build system. Package metadata is defined in build.zig.zon files, which use Zig’s ZON (Zig Object Notation) format.

Package Manifest (build.zig.zon)

The build.zig.zon file describes your package and its dependencies.

Basic Structure

.{
    .name = "myproject",
    .version = "0.1.0",
    .dependencies = .{},
    .paths = ."",
}

Complete Example

lib/std/Build.zig:1-17
// The Zig compiler is not intended to be consumed as a package.
// The sole purpose of this manifest file is to test the compiler.
.{
    .name = .zig,
    .version = "0.0.0",
    .dependencies = .{
        .standalone_test_cases = .{
            .path = "test/standalone",
        },
        .link_test_cases = .{
            .path = "test/link",
        },
    },
    .paths = ."",
    .fingerprint = 0xc1ce108124179e16,
}

Package Fields

Required Fields

1
.name
2
The package name, used as an identifier:
3
.name = "my-library",
4
Or as an identifier literal:
5
.name = .my_library,
6
.version
7
Semantic version string:
8
.version = "1.2.3",
9
.paths
10
Files and directories to include in the package:
11
.paths = .{
    "build.zig",
    "build.zig.zon",
    "src",
    "lib",
    "LICENSE",
    "README.md",
},
12
Or include everything:
13
.paths = ."",

Optional Fields

.dependencies - External package dependencies .fingerprint - Cache validation hash (auto-generated)

Dependencies

Dependencies can reference local paths, URLs, or git repositories.

Local Path Dependencies

.dependencies = .{
    .my_module = .{
        .path = "../my-module",
    },
    .test_cases = .{
        .path = "test/standalone",
    },
},

URL Dependencies

.dependencies = .{
    .ziglibs = .{
        .url = "https://github.com/user/repo/archive/commit-hash.tar.gz",
        .hash = "12208d2b8c95e6e5d2e1e5b5a5c5e5f5a5c5e5f5a5c5e5f5a5c5e5f5a5c5e5f5",
    },
},
When adding a URL dependency without a hash, run zig build and Zig will report the expected hash that you can add to your manifest.

Git Dependencies

.dependencies = .{
    .example = .{
        .url = "git+https://github.com/user/repo#branch-or-tag",
        .hash = "1220...",
    },
},

Using Dependencies in build.zig

Accessing Dependencies

Dependencies are accessed through the dependency() function:
const my_module = b.dependency("my_module", .{
    .target = target,
    .optimize = optimize,
});

Importing Modules from Dependencies

// Get a module from a dependency
const dep_module = my_module.module("library");

// Add it to your executable
exe.root_module.addImport("mylib", dep_module);
In your source code:
const mylib = @import("mylib");

pub fn main() void {
    mylib.doSomething();
}

Passing Options to Dependencies

You can pass build options when loading a dependency:
const my_dep = b.dependency("my_dep", .{
    .target = target,
    .optimize = optimize,
    .enable_feature = true,
    .max_connections = 100,
});
The dependency’s build.zig can access these via b.option().

Creating Modules for Export

Public Modules

Create modules that other packages can import:
// In your build.zig
const mylib = b.addModule("mylib", .{
    .root_source_file = b.path("src/lib.zig"),
});
Other packages can then access it:
const dep = b.dependency("your_package", .{...});
const mylib = dep.module("mylib");
exe.root_module.addImport("mylib", mylib);

Private Modules

Create modules for internal use only:
const internal_mod = b.createModule(.{
    .root_source_file = b.path("src/internal.zig"),
});

Dependency Resolution

Zig’s package manager uses content-addressable storage:
1
Cache Location
2
Dependencies are stored in the global cache:
3
~/.cache/zig/p/  (Linux/macOS)
%LOCALAPPDATA%\zig\p\  (Windows)
4
Hash Verification
5
The .hash field uses the multihash format:
6
  • First 4 hex chars: Hash algorithm ID (1220 = SHA-256)
  • Remaining chars: Hash value
  • 7
    Fingerprint
    8
    The .fingerprint field caches the hash of your package contents. Zig regenerates it when needed.

    Package Organization Best Practices

    myproject/
    ├── build.zig
    ├── build.zig.zon
    ├── src/
    │   ├── main.zig
    │   └── lib.zig
    ├── test/
    │   └── tests.zig
    ├── LICENSE
    └── README.md
    

    Exporting Multiple Modules

    // Export different modules for different use cases
    const core = b.addModule("core", .{
        .root_source_file = b.path("src/core.zig"),
    });
    
    const utils = b.addModule("utils", .{
        .root_source_file = b.path("src/utils.zig"),
    });
    
    const extras = b.addModule("extras", .{
        .root_source_file = b.path("src/extras.zig"),
    });
    extras.addImport("core", core);
    
    Consumers can import selectively:
    const dep = b.dependency("mylib", .{});
    exe.root_module.addImport("core", dep.module("core"));
    exe.root_module.addImport("utils", dep.module("utils"));
    

    Working with Dependencies

    Available Dependencies

    Check available dependencies at build time:
    lib/std/Build.zig:135
    const AvailableDeps = []const struct { []const u8, []const u8 };
    
    The available_deps field maps dependency names to their package hashes.

    Dependency Caching

    lib/std/Build.zig:152-156
    const InitializedDepKey = struct {
        build_root_string: []const u8,
        user_input_options: UserInputOptionsMap,
    };
    
    Dependencies are cached based on:
    • Build root path
    • User input options (target, optimize, custom options)
    This ensures the same dependency with different options is built separately.

    Transitive Dependencies

    Zig automatically handles transitive dependencies. If package A depends on package B, and package B depends on package C, all three will be resolved and cached correctly.

    Lazy Dependencies

    lib/std/Build.zig:125
    needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .empty,
    
    Dependencies are only fetched and built when actually used in the build process.

    Example: Multi-Package Project

    Root Package (build.zig.zon)

    .{
        .name = "myapp",
        .version = "1.0.0",
        .dependencies = .{
            .network = .{
                .path = "../network-lib",
            },
            .utils = .{
                .url = "https://example.com/utils-v2.tar.gz",
                .hash = "1220abcd...",
            },
        },
        .paths = ."",
    }
    

    Root Package (build.zig)

    const std = @import("std");
    
    pub fn build(b: *std.Build) void {
        const target = b.standardTargetOptions(.{});
        const optimize = b.standardOptimizeOption(.{});
    
        // Load dependencies
        const network = b.dependency("network", .{
            .target = target,
            .optimize = optimize,
        });
        
        const utils = b.dependency("utils", .{
            .target = target,
            .optimize = optimize,
        });
    
        const exe = b.addExecutable(.{
            .name = "myapp",
            .root_module = b.createModule(.{
                .root_source_file = b.path("src/main.zig"),
                .target = target,
                .optimize = optimize,
            }),
        });
    
        // Import dependency modules
        exe.root_module.addImport("network", network.module("network"));
        exe.root_module.addImport("utils", utils.module("utils"));
    
        b.installArtifact(exe);
    }
    

    Troubleshooting

    Hash Mismatches

    If you see a hash mismatch error:
    1. Remove the .hash field from build.zig.zon
    2. Run zig build
    3. Copy the expected hash from the error message
    4. Add it to your manifest

    Updating Dependencies

    To update a dependency:
    1. Update the URL or path in build.zig.zon
    2. Remove or update the hash
    3. Run zig build to get the new hash
    4. Update the manifest with the new hash

    Cache Issues

    To clear the dependency cache:
    rm -rf ~/.cache/zig/p/
    
    Then run zig build to re-download dependencies.

    Build docs developers (and LLMs) love