
Zig Build System
- 312 installs
- 155 repo stars
- Updated June 27, 2026
- mohitmishra786/low-level-dev-skills
Author and maintain Zig build.zig files, declare targets, manage deps, and run reproducible native builds for low-level systems projects.
About
Guides agents through Zig's build system: structuring build.zig, defining build steps, linking C/Zig modules, caching artifacts, and running zig build for systems and CLI targets in mohitmishra786/low-level-dev-skills.
- build.zig target and step design
- Dependency and module graph setup
- Reproducible native compile workflows
- Cross-target artifact configuration
- Low-level systems project scaffolding
Zig Build System by the numbers
- 312 all-time installs (skills.sh)
- +24 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #170 of 550 CLI & Terminal skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill zig-build-systemAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 312 |
|---|---|
| repo stars | ★ 155 |
| Last updated | June 27, 2026 |
| Repository | mohitmishra786/low-level-dev-skills ↗ |
What it does
Author and maintain Zig build.zig files, declare targets, manage deps, and run reproducible native builds for low-level systems projects.
Files
Zig Build System
Purpose
Guide agents through writing build.zig files: executables, libraries, C source integration, build options, test configuration, and build.zig.zon package manifests.
Triggers
- "How do I set up a build.zig file?"
- "How do I add a C library to a Zig project?"
- "How do I define build-time options in Zig?"
- "How do I run Zig tests with zig build test?"
- "What is build.zig.zon and how do I use it?"
- "How do I add a Zig package dependency?"
Workflow
1. Project initialization
# Initialize a new project
mkdir myproject && cd myproject
zig init # creates src/main.zig and build.zig
# Build
zig build
# Run
zig build run
# Test
zig build test2. build.zig structure
const std = @import("std");
pub fn build(b: *std.Build) void {
// Standard options (--optimize, --target)
const optimize = b.standardOptimizeOption(.{});
const target = b.standardTargetOptions(.{});
// Executable
const exe = b.addExecutable(.{
.name = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Install step (zig build → copies to zig-out/bin/)
b.installArtifact(exe);
// Run step (zig build run)
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);
// Test step (zig build test)
const unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}3. Libraries
// Static library
const lib = b.addStaticLibrary(.{
.name = "mylib",
.root_source_file = b.path("src/mylib.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(lib);
// Shared library
const shared_lib = b.addSharedLibrary(.{
.name = "mylib",
.root_source_file = b.path("src/mylib.zig"),
.target = target,
.optimize = optimize,
.version = .{ .major = 1, .minor = 0, .patch = 0 },
});
b.installArtifact(shared_lib);
// Link library into executable
exe.linkLibrary(lib);4. Adding C source files
// Single C file
exe.addCSourceFile(.{
.file = b.path("src/legacy.c"),
.flags = &.{ "-std=c11", "-Wall", "-Wextra" },
});
// Multiple C files
exe.addCSourceFiles(.{
.files = &.{
"src/a.c",
"src/b.c",
"src/c.c",
},
.flags = &.{ "-std=c11", "-O2" },
});
// Include directories
exe.addIncludePath(b.path("include/"));
exe.addIncludePath(.{ .cwd_relative = "/usr/local/include" });
// System libraries
exe.linkSystemLibrary("curl");
exe.linkSystemLibrary("ssl");
exe.linkLibC(); // link libc (required if calling C stdlib)5. Build-time options
pub fn build(b: *std.Build) void {
// Boolean option
const enable_logging = b.option(
bool,
"logging",
"Enable debug logging",
) orelse false;
// Enum option
const Backend = enum { opengl, vulkan, software };
const backend = b.option(
Backend,
"backend",
"Rendering backend",
) orelse .opengl;
// Integer option
const max_connections = b.option(
u32,
"max-connections",
"Maximum concurrent connections",
) orelse 64;
// Pass to Zig code as compile-time constant
const options = b.addOptions();
options.addOption(bool, "enable_logging", enable_logging);
options.addOption(Backend, "backend", backend);
options.addOption(u32, "max_connections", max_connections);
exe.root_module.addOptions("build_options", options);
}In Zig source:
const build_options = @import("build_options");
pub fn main() void {
if (build_options.enable_logging) {
std.debug.print("Logging enabled\n", .{});
}
}# Pass options on command line
zig build -Dlogging=true -Dbackend=vulkan -Dmax-connections=2566. Module system
// Create a module (reusable across targets)
const mymodule = b.addModule("mymodule", .{
.root_source_file = b.path("src/mymodule.zig"),
});
// Use module in executable
exe.root_module.addImport("mymodule", mymodule);
// Share module between exe and tests
const utils = b.addModule("utils", .{
.root_source_file = b.path("src/utils.zig"),
});
exe.root_module.addImport("utils", utils);
unit_tests.root_module.addImport("utils", utils);In Zig source:
const utils = @import("utils");
const mymodule = @import("mymodule");7. Package management with build.zig.zon
// build.zig.zon
.{
.name = "myapp",
.version = "0.1.0",
.minimum_zig_version = "0.13.0",
.dependencies = .{
.zig_clap = .{
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.9.1.tar.gz",
.hash = "1220...", // Run zig build to get the hash
},
.known_folders = .{
.url = "https://github.com/ziglibs/known-folders/archive/refs/heads/master.tar.gz",
.hash = "1220...",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"LICENSE",
"README.md",
},
}// build.zig — use the dependency
const clap_dep = b.dependency("zig_clap", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("clap", clap_dep.module("clap"));# Fetch dependencies (creates zig-cache/packages/)
zig build # auto-fetches on first run
# Zig will print the hash if missing — copy it into build.zig.zon8. Custom build steps
// Code generation step
const gen_step = b.addSystemCommand(&.{
"python3", "scripts/gen.py", "--output", "src/generated.zig",
});
exe.step.dependOn(&gen_step.step);
// Custom install step
const install_config = b.addInstallFile(
b.path("config/default.toml"),
"share/myapp/config.toml",
);
b.getInstallStep().dependOn(&install_config.step);For advanced build.zig patterns, see references/build-zig-patterns.md.
Related skills
- Use
skills/zig/zig-compilerfor single-file builds and compiler flags - Use
skills/zig/zig-cinteropfor C library integration in build.zig - Use
skills/zig/zig-crossfor cross-compilation in build.zig - Use
skills/build-systems/cmakewhen embedding Zig into a CMake project
build.zig Advanced Patterns Reference
Multi-target Builds
pub fn build(b: *std.Build) void {
const targets = [_]std.Target.Query{
.{ .cpu_arch = .x86_64, .os_tag = .linux },
.{ .cpu_arch = .aarch64, .os_tag = .linux },
.{ .cpu_arch = .x86_64, .os_tag = .windows },
.{ .cpu_arch = .aarch64, .os_tag = .macos },
};
for (targets) |t| {
const target = b.resolveTargetQuery(t);
const exe = b.addExecutable(.{
.name = b.fmt("myapp-{s}-{s}", .{
@tagName(t.cpu_arch.?),
@tagName(t.os_tag.?),
}),
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = .ReleaseFast,
});
b.installArtifact(exe);
}
}Conditional Compilation
// Based on target
const builtin = @import("builtin");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Platform-specific sources
const resolved = target.result;
switch (resolved.os.tag) {
.linux => exe.addCSourceFile(.{
.file = b.path("src/platform/linux.c"),
.flags = &.{"-std=c11"},
}),
.windows => exe.addCSourceFile(.{
.file = b.path("src/platform/windows.c"),
.flags = &.{"-std=c11"},
}),
.macos => exe.addCSourceFile(.{
.file = b.path("src/platform/macos.c"),
.flags = &.{"-std=c11"},
}),
else => {},
}
// Windows-specific linking
if (resolved.os.tag == .windows) {
exe.linkSystemLibrary("ws2_32");
exe.linkSystemLibrary("advapi32");
}
}External C Library Integration
With pkg-config
// Link library found via pkg-config
exe.linkSystemLibrary2("libcurl", .{ .use_pkg_config = .force });
exe.linkSystemLibrary2("openssl", .{ .use_pkg_config = .try_first });
exe.linkLibC();With explicit paths (no pkg-config)
const lib_path = b.path("vendor/mylib/lib");
const include_path = b.path("vendor/mylib/include");
exe.addLibraryPath(lib_path);
exe.addIncludePath(include_path);
exe.linkSystemLibrary("mylib");
exe.linkLibC();Build C library from source
const mylib = b.addStaticLibrary(.{
.name = "mylib",
.target = target,
.optimize = optimize,
});
mylib.addCSourceFiles(.{
.files = &.{
"vendor/mylib/src/a.c",
"vendor/mylib/src/b.c",
},
.flags = &.{ "-std=c99", "-fPIC" },
});
mylib.addIncludePath(b.path("vendor/mylib/include"));
mylib.linkLibC();
exe.linkLibrary(mylib);
exe.addIncludePath(b.path("vendor/mylib/include"));Testing Patterns
// Separate test binary per module
const lib_tests = b.addTest(.{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
.test_runner = b.path("test_runner.zig"), // Custom test runner
});
// Filter tests by name
const run_lib_tests = b.addRunArtifact(lib_tests);
run_lib_tests.addArg("--test-filter=my_test_prefix");
// Integration tests
const integration_tests = b.addTest(.{
.root_source_file = b.path("tests/integration.zig"),
.target = target,
.optimize = optimize,
});
integration_tests.root_module.addImport("mylib", mymodule);
const test_step = b.step("test", "Run all tests");
test_step.dependOn(&b.addRunArtifact(lib_tests).step);
test_step.dependOn(&b.addRunArtifact(integration_tests).step);Install Layout Control
// Default: zig-out/bin/, zig-out/lib/
b.installArtifact(exe);
// Custom install directory
b.installFile(b.path("config/default.conf"), "etc/myapp/default.conf");
b.installDirectory(.{
.source_dir = b.path("assets"),
.install_dir = .prefix,
.install_subdir = "share/myapp/assets",
});
// Install headers
b.installFile(b.path("src/mylib.h"), "include/mylib.h");
// Change install prefix at build time
// zig build --prefix /usr/localCustom Build Steps and Runners
// Generate version file
const version_step = b.addWriteFile("src/version.zig",
b.fmt(
\\pub const version = "{}";
\\pub const git_hash = "{}";
, .{ b.version, "abc1234" }),
);
exe.step.dependOn(&version_step.step);
// Run code generator
const gen = b.addSystemCommand(&.{
"python3",
b.pathFromRoot("scripts/gen_bindings.py"),
"--input", b.pathFromRoot("schema.json"),
"--output", "src/bindings.zig",
});
exe.step.dependOn(&gen.step);
// Custom step alias
const check_step = b.step("check", "Check for compile errors");
check_step.dependOn(&exe.step);Dependency Tree
// Print dependency tree
// zig build --verbose
// Shows all steps and their dependencies
// Force rebuild
// zig build --forceBuild Variables Available
pub fn build(b: *std.Build) void {
_ = b.graph.zig_exe; // Path to zig compiler
_ = b.graph.env_map; // Environment variables
_ = b.install_prefix; // Install prefix (--prefix)
_ = b.cache_root; // Cache directory
_ = b.global_cache_root; // Global cache
_ = b.build_root; // Project root
}