I watched Zig Build System Basics yesterday and had some scattered thoughts about the build system.
First off, I think the build system has improved greatly since I picked up Zig in 0.11.0, and I think it’s heading in the right direction. However, I can’t help but complain about the boilerplate needed to set up a new project. I don’t use zig init
because I don’t like all the comments and superfluous examples it puts in the generated files. It’s great for someone just getting started, but for someone who’s done it dozens of times it seems like it’s almost faster to just write it from scratch by hand each time than to use it and remove/rename the generated content. Lately, I haven’t been writing a build.zig
and instead just putting all my logic into a single file and calling zig run myfile.zig
or zig build-exe
on it. However, the second I need a dependency, I write a build.zig
.
I actually think a minimal zig init
would be great: it wouldn’t add any comments to any of the generated files; it would add only the minimal subset of project setup (a build.zig
that builds a single executable). I think it would also be nice to have another flag where we could specify whether we wanted to create a library (i.e. a .so
or .a
/.dll
or .lib
), a module, or an executable.
Most of my build.zig
s look nearly identical (aside from some variable names). It’s not until I get much further downstream that I need to reach into the toolbox (addSystemCommand
, linkSystemLibrary
, etc.). In my experience, many projects I’ve seen on GitHub and elsewhere look nearly identical as well. It’s not until the package provides cross-platform behavior not found in the build system that the build.zig
begins to change.
So, I was thinking: what if zig build
could detect if build.zig.zon
was present but build.zig
was absent, and provide a default build.zig
implementation based on some conventions. For example, if src/main.zig
exists, it’s built into an executable and given the name retrieved from the name
field in the build.zig.zon
. Similarly, if src/root.zig
exists, it’s built into a module that’s automatically added to the exe’s imports. Additionally, the default build script could parse the dependencies out of the build.zig.zon
and add them as imports to the modules as well.
I feel like this would work for the vast majority of Zig users that are either just starting out or users that are building simple applications and tools that don’t need complex build logic. When a user does need more complex build logic, or they want to stray from the main.zig
/root.zig
convention, they can provide their own build.zig
and it would function as it does now.
This idea is obviously not novel, and closely resembles Cargo for Rust: you don’t need a build.rs
unless you need more complex build logic. However, my experience with Cargo and build.rs
is that it’s more of a hook into the build system than the build system itself. Users could use zig build-exe
directly, but I think zig build
is more natural and human-friendly, whereas zig build-exe
is intended to be wrapped by a higher-level script/application.
Anyways, that’s about all I have. Just some random thoughts. I’m not petitioning for a change or anything, but I would like to know what others think (except maybe some improvements/additions to zig init
, that would be cool).