How to zig a C project?

A few weeks ago Andrew and Kristoff made a video about converting C projects/libs to the Zig build system. There was a very clear explanation by Andrew about how the cache system works and explanation about the different conversion approaches. Anyway, for a stupid person like me, that was a precious source of information but for some reason, twitch videos are ephemeral and now it’s all gone.

One approach was to fork the C project/lib and add a build.zig to it. What was the alternative?

2 Likes

I don’t know the video you’re referring to, but in the official build system documentation, there were some unfinished sections related to package management, one of them being related to packaging a C library, and the subheadings listed two approaches: one is the fork approach you’re referring to, and the other is titled the “pristine tarball strategy”.

What I believe this is referring to is the ability of the Zig package manager to fetch non-Zig dependencies (e.g. plain tarball distributions of C libraries) and then refer to files and directories within them using std.Build.Dependency.path, which returns a std.Build.LazyPath referring to the path within the package.

Here’s an example of a PR I made to a project a little while ago to convert it from the fork strategy to the tarball strategy: Update to latest Zig master and use package manager by ianprime0509 · Pull Request #1 · mitchellh/zig-build-libxml2 · GitHub Here, the build.zig.zon has a libxml2 dependency which fetches an upstream release tarball as-is: https://github.com/ianprime0509/zig-build-libxml2/blob/update-zig/build.zig.zon#L12-L18 This tarball doesn’t have any build.zig, so it has to be treated as a plain bundle of files. Since most build-related functions use LazyPath to refer to paths, you can then pretty much just write your build.zig as you would if you forked the project, but replace LazyPaths like .{ .path = "foo/bar" } with upstream.path("foo/bar") so they refer to the path within the tarball you fetched (example: https://github.com/ianprime0509/zig-build-libxml2/blob/update-zig/build.zig#L16).

There are pros and cons to both approaches. If you’re going to be maintaining the project long-term and making changes to it, I think the fork strategy makes sense; on the other hand, if all you want to do is package an existing library without changing any of its code, I think the upstream tarball approach is better, since it makes it easier for you as a maintainer to manage updates from upstream and for users to verify that no changes have been made to the upstream sources.

6 Likes