How to package a Zig source module
- In a zig source file, write public zig functions or types.
- In
build.zigadd a module for the zig source file. - Create a
build.zig.zonfor the package, include all the source and build files in thepath.
Example
- file:
src/lib.zig, publicsayfunction.
const std = @import("std");
pub fn say(what: []const u8) void {
std.debug.print("{s}\n", .{what});
}
- file
build.zig,src/lib.zigbecomesspeakmodule.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
_ = b.addModule("speak", .{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
}
- file
build.zig.zon,
.{
.name = .zig_speak,
.version = "0.1.0",
.fingerprint = 0xdeadbeef, //generated by zig
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
That’s all. Your package is now usable. You can publish it or use it as it is.
The name field is an enum literal, if you want a name that isn’t a valid zig identifier use the .@"..." syntax.
The fingerprint, in combination with name, is used to identify your package.
zig init will generate one for you. Or if you create the file manually, leave the field out and zig build will error and provide a generated value you can then copy-paste into the field.
That allows packages to have the same name, but also requires that forks update the fingerprint so that the package manager can differentiate between them. Failing to do so is hostile to the upstream project, as the fork would be claiming to be upstream. (forks that exist just to PR are a reasonable exception)
Documentation
How to use the package
- Use
zig initto add an executable or a library that imports the module. - Reference the package in
build.zig.zon. - In
build.zigimport the module from the package.
Example
- Start a new project
zig-helloby runningzig init
file src/main.zig
const std = @import("std");
const speak = @import("speak");
pub fn main() void {
speak.say("Hello, Packaged Module!\n");
}
- Run
zig fetch --save ../zig-speak, this creates or updates the file:build.zig.zon
../zig-speakis the path to the zig-speak package in our disk.
.{
.name = .zig_hello,
.version = "0.0.0",
.dependencies = .{
.zig_speak = .{
.path = "../zig-speak",
},
},
.paths = .{
"",
},
}
- Get the module from the package and import it.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// load the "zig-speak" dependency from build.zig.zon
const package = b.dependency("zig_speak", .{
.target = target,
.optimize = optimize,
});
// load the "speak" module from the package
const module = package.module("speak");
const exe = b.addExecutable(.{
.name = "zig-hello",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// make the module usable as @import("speak")
exe.root_module.addImport("speak", module);
b.installArtifact(exe);
}
Build and run:
> zig build
> zig-out/bin/zig-hello
Hello, Packaged Module!
Use a published package
When calling zig fetch --save you can provide the git http(s) path of a git repository (other protocols and file formats are possible).
For example, you can push the zig-speak package code to a github repository at https://github.com/username/zig-speak and access the package as:
zig fetch --save git+https://github.com/username/zig-speak/#HEAD
the added dependency will look something like:
.dependencies = .{
.zig_speak = .{
.url = "git+https://github.com/username/zig-speak/#1231410123",
.hash = "zig_speak-0.1.0-hhasflAjfasdflADSF80123..."
},
},
#refrefers to branches, tags, or commits
refering to a branch orHEADshould only be done withzig fetchas it will resolve to a specific commit before updatingbuild.zig.zon
doing so inbuild.zig.zoninstead may result in later refetching causing a hash conflict error as it downloaded a newer commit!
It is also possible to depend on tarballs and zip archives, in which case you would remove the git+ and #ref from the URL if fetching remotely.