Using Zig’s Build System for C/C++ Projects in 2025
Zig is a good programming language with a nice build system alongside its drop-in replacement for the C/C++ compiler.
Hello Zig Build System
Remember that I use the latest unstable Zig version, so this might not work for you.
It’s fairly simple to use. I will create two files for the starter: build.zig
and main.c
file.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const mode = b.standardOptimizeOption(.{});
const module = b.addModule("main", .{
.target = target,
.optimize = mode,
.link_libc = true,
});
module.addCSourceFile(.{
.file = b.path("main.c"),
.flags = &[_][]const u8{"-std=c11"},
});
const exe = b.addExecutable(.{
.name = "hello",
.root_module = module,
});
b.installArtifact(exe);
}
#include <stdio.h>
int main() {
printf("Hello from Zig Build System");
return 0;
}
All we need to do is run the following command on the terminal.
zig build
This command will compile the main.c
file and link it together to create the hello
executable file. You’ll find it in the zig-out/bin
folder, which is right in your current working directory. If you run the executable with the ./zig-out/bin/hello
command line, it will print the following string, which is exactly what we expected.
Hello from Zig Build System!
Running with Zig
We can use the zig build run
command to compile and run the executable in one go. All we have to do is add the following lines to the build
function in the build.zig
file.
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
The new lines in the build system instruct it to add a run command that depends on the previous install step. This makes sense because we can’t run the program without an executable. Next, it checks if there are any command-line arguments passed to the Zig Build System and adds them to the run command. Finally, we enable the run command by adding it as a run step.
For example, if our program requires command line arguments passed to it when it runs, then the Zig build command becomes
zig build run -- arg1 arg2 arg3
Since our hello world program doesn’t need command line arguments, we can omit them. Running the zig build run
command will produce the same output as before.
Hello from Zig Build System!
Conclusion
We can use the Zig build system alongside its C compiler replacement for our C projects that we still want to work on and maintain in 2025 and beyond. We started with a basic ‘hello world’ program, and I’m sure I’ll share more as I explore more useful features of the Zig build system.