zig
Zig runbook: build/test, comptime patterns, allocators, build.zig/build.zig.zon, zero-copy parsing, C interop.
$ 安裝
git clone https://github.com/tkersey/dotfiles /tmp/dotfiles && cp -r /tmp/dotfiles/codex/skills/zig ~/.claude/skills/dotfiles// tip: Run this command in your terminal to install the skill
SKILL.md
name: zig description: "Zig runbook: build/test, comptime patterns, allocators, build.zig/build.zig.zon, zero-copy parsing, C interop."
Zig
When to use
- Editing
.zigfiles. - Modifying
build.zigorbuild.zig.zon. - Zig builds/tests, dependencies, cross-compilation.
- Comptime, reflection, codegen.
- Allocators, ownership, zero-copy parsing.
- C interop.
Quick start
# Initialize
zig init-exe
zig init-lib
# Build/run/test
zig build
zig build run
zig build test
zig test src/main.zig
Common commands
# Release
zig build -Doptimize=ReleaseFast
# Cross-compile
zig build -Dtarget=x86_64-linux
zig build -Dtarget=aarch64-macos
# Clean artifacts
rm -rf zig-out zig-cache
Comptime essentials
comptimeparameters drive generics.comptime { ... }forces compile-time evaluation.inline for/inline whileunroll at compile time.@typeInfoenables reflection;@compileErrorenforces invariants.- If compile-time loops blow up, consider
@setEvalBranchQuota(surgical use only).
Comptime example
const std = @import("std");
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
test "comptime parameter" {
const x = max(u32, 3, 5);
try std.testing.expect(x == 5);
}
Build essentials (build.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 = "my-app",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
Package management (build.zig.zon)
.{
.name = "my-project",
.version = "0.1.0",
.dependencies = .{
.@"some-package" = .{
.url = "https://github.com/user/package/archive/main.tar.gz",
.hash = "1220abcdef...",
},
},
.paths = .{ "build.zig", "build.zig.zon", "src" },
}
Memory / allocators
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const bytes = try allocator.alloc(u8, 100);
defer allocator.free(bytes);
}
Zero-copy parsing playbook
Principles:
- Treat input as immutable bytes; parse into views, not copies.
- Make ownership explicit (borrowed vs owned).
- Store spans/offsets into a stable base buffer.
- Never return slices into temporary buffers.
Borrowed/owned token (copy-on-write escape hatch)
const std = @import("std");
pub const ByteView = union(enum) {
borrowed: []const u8,
owned: []u8,
pub fn slice(self: ByteView) []const u8 {
return switch (self) {
.borrowed => |s| s,
.owned => |s| s,
};
}
pub fn toOwned(self: ByteView, allocator: std.mem.Allocator) ![]u8 {
return switch (self) {
.owned => |s| s,
.borrowed => |s| try allocator.dupe(u8, s),
};
}
pub fn deinit(self: *ByteView, allocator: std.mem.Allocator) void {
if (self.* == .owned) allocator.free(self.owned);
self.* = .{ .borrowed = &.{} };
}
};
POSIX mmap (stable base buffer)
const std = @import("std");
pub const MappedFile = struct {
data: []const u8,
owns: bool,
pub fn open(path: []const u8) !MappedFile {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
const size = (try file.stat()).size;
const map = try std.posix.mmap(
null,
size,
std.posix.PROT.READ,
.{ .TYPE = .PRIVATE },
file.handle,
0,
);
return .{ .data = map, .owns = true };
}
pub fn close(self: *MappedFile) void {
if (self.owns) std.posix.munmap(self.data);
self.* = .{ .data = &.{}, .owns = false };
}
};
Span-based parsing (offsets, not copies)
const Span = struct {
base: []const u8,
start: usize,
len: usize,
pub fn slice(self: Span) []const u8 {
return self.base[self.start..][0..self.len];
}
};
Testing
- Leak detection: use
std.testing.allocatoranddeferfrees. - Allocation counting: wrap an allocator and assert zero allocations for a “zero-copy” path.
- OOM injection: run under
std.testing.FailingAllocator. - Exhaustive OOM:
std.testing.checkAllAllocationFailures.
C interop
const c = @cImport({
@cInclude("stdio.h");
});
pub fn main() void {
_ = c.printf("Hello from C!\n");
}
Pitfalls
- Make ownership explicit; always free heap allocations.
- Avoid returning slices backed by stack memory.
[*c]Tis nullable;[*]Tis non-null.- Use
zig fetch --saveto populatebuild.zig.zonhashes.
Activation cues
- "zig" / "ziglang" / ".zig"
- "build.zig" / "build.zig.zon"
- "zig build" / "zig test"
- "comptime" / "allocator" / "@typeInfo" / "@compileError"
