dasimmet/zig_pkg_tool
a command line tool to work with build.zig dependencies and build graphs
aa24df42183ad415d10bc0a33e6238c437fc0f59
a command line tool to work with build.zig
dependencies and build graphs.
It embeds custom build runners to retrieve build graph information,
used to backup dependencies, output a graphviz dot
file etc.
The repo vendors zig's build-runner.zig
with an inserted hook
to serialize the std.Build
struct to zon
and send it from the subpocess stdout
back to zigpkg
.
Then that information is used to perform operations based on the build graph.
It is compatible and requires with zig >= 0.14.0
at runtime, when zig master
starts making changes to the build runner the vendored runner needs to be versioned
inside this tool.
> zig build
> ./zig-out/bin/zigpkg --help
# or:
> zig build zigpkg -- --help
usage: zigpkg <subcommand> [--help]
stores all dependencies of a directory containing build.zig.zon in a .tar.gz archive
available subcommands:
dot rerun "zig build" and output a graphviz ".dot" file of build steps based on args
dotall rerun "zig build" and output a graphviz ".dot" file of all build steps
zon rerun "zig build" with a custom build runner and output the build graph as .zon to stdout
json same as "zon" but output json
deppkg more subcommands for creating and working with "deppkg.tar.gz" files storing all
dependencies required to build a zig package
environment variables:
ZIG: path to the zig compiler to invoke in subprocesses. defaults to "zig".
The "deppkg create" subcommand generates a single archive containing all dependencies zig fetches for same arguments you would provide to "zig build".
The file can be verified with the "deppkg extract" subcommand, which repacks the individual dependencies into temporary tar archives, loads them back into zigs package cache with "zig fetch", and compares the hash generated by zig with the archive.
So when releasing a zig project with dependencies, you can include the deppkg archive as a complete source distribution that is buildable even when upstream dependencies become unavailable for whatever reason.
Be aware that not all lazy dependencies may be fetched depending on the provided arguments (and even the "native target" if some host build steps switch out dependencies based on it). This means the user is to provide build options that will fetch all dependencies he expects to be in the package.
For now, this tool does not use the exact same filter logic as zig's filter on the paths
field of build.zig.zon
, so it cannot guarantee that the packaged dependencies
produce the same hash. In that case the extract command will fail. That could be
avoided by vendoring zig's Manifest parser or making it available in the standard
library in the future.
Not applying any filter would be an option too, but other tools
like a misconfigured zls
may write files into the zig package cache and add
files we dont want too include in the package:
ls ~/.cache/zig/p/known_folders-0.0.0-Fy-PJtLDAADGDOwYwMkVydMSTp_aN-nfjCZw6qPQ2ECL/.zig-cache
h o tmp z
this executes zig build
with a custom build runner (including potiential additional arguments),
to convert the Build.Step
graph to basic graphviz dot
code.
that can be easily be converted to the svg form.
For now, generated dot strings are not escaped and might break.
Since the build graph is dependent on the original invocation of zig build
,
integration into the build system is not easy. It's easier to build zigpkg
manually, and invoke zigpkg dot <build_root> [zig build ards]
with the same arguments
as zig build
.
# cli
./zig-out/bin/zigpkg dot . install | dot -Tsvg > graph.svg
// build.zig usage
// - the disadvantage here is, `dotGraphStep` basically reruns `zig build`,
// and passes the extra arguments down, but does not know about the original arguments.
// - svgGraph is a system "dot" command
const zig_pkg_tool = @import("pkg_tool");
const svggraph = zig_pkg_tool.svgGraph(b, zig_pkg_tool.dotGraphStep(b, &.{
"install", // extra args zig build, e.g. targets
"dot",
"test",
"run",
}).captureStdOut());
b.step("dot", "install graph.svg").dependOn(&b.addInstallFile(
svggraph,
"graph.svg",
).step);