पाठ 20 / 25

Packages and Dependencies with build.zig.zon

Add dependencies with zig fetch and use them in build.zig.

A decentralised package manager

Zig's package manager is built into the build system and is decentralised: there is no central registry. build.zig.zon (Zig Object Notation) declares the package's name, version, minimum Zig version, a fingerprint identifying the package, the paths included when others depend on it, and its dependencies. Each dependency has a URL (often a release tarball or a git commit archive) and a content hash, so builds are reproducible and tamper-evident: if the downloaded content changes, the build fails. Add a dependency with zig fetch --save <url>, which downloads it, computes the hash and edits build.zig.zon. In build.zig, b.dependency("name", .{ .target = target, .optimize = optimize }) gives access to the dependency's modules and artifacts, and addImport makes a module importable in your code. Packages can also wrap C libraries, building them from source with Zig, which gives C projects reproducible cross-platform builds without system packages. Dependencies are cached globally, and --fetch downloads everything ahead of offline builds.

Adding and using a dependency

zig fetch, build.zig.zon and wiring a module into the build.

// Shell:
//   zig fetch --save git+https://github.com/<owner>/<zig-library>#<commit-or-tag>

// build.zig.zon (after zig fetch; values are examples)
// .{
//     .name = .invoices,
//     .version = "0.1.0",
//     .fingerprint = 0x9a3c51f0d2e47b16,
//     .minimum_zig_version = "0.15.1",
//     .dependencies = .{
//         .csv = .{
//             .url = "git+https://github.com/<owner>/<zig-library>#<commit>",
//             .hash = "<hash written by zig fetch>",
//         },
//     },
//     .paths = .{ "build.zig", "build.zig.zon", "src" },
// }

// build.zig (excerpt)
const std = @import("std");

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

    const csv_dep = b.dependency("csv", .{ .target = target, .optimize = optimize });

    const exe = b.addExecutable(.{
        .name = "invoices",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{
                .{ .name = "csv", .module = csv_dep.module("csv") },   // @import("csv")
            },
        }),
    });
    b.installArtifact(exe);
}

A recipe with sealed ingredient jars

build.zig.zon is a recipe that lists where each ingredient comes from and the seal number on its jar (the hash). If someone swaps the contents, the seal does not match and the kitchen refuses to cook.

त्वरित जाँच: What does the hash in a build.zig.zon dependency guarantee?

  • Faster downloads
  • That the package is popular
  • That it was reviewed by the Zig team
  • That the fetched content is exactly what was recorded, making builds reproducible
Answer

That the fetched content is exactly what was recorded, making builds reproducible — Content hashes detect any change in the downloaded package.