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.zigs 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).