Using Zig’s Build System for C/C++ Projects in 2025

Alwin Arrasyid
2 min readJan 18, 2025

--

Zig is a good programming language with a nice build system alongside its drop-in replacement for the C/C++ compiler.

Generated by DALL-E.

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.

--

--

Alwin Arrasyid
Alwin Arrasyid

Written by Alwin Arrasyid

Principal Engineer, working on better IoT solutions and enabling AI on the edge.

No responses yet