commit 745b38fde2b7e3e8369874aee3709fe18eb39a11 (tree)
parent 3750469dcac7711374002835f569bcdf1df75f4d
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Tue, 10 Feb 2026 14:26:56 +0000
`zig build` does more and in parallel
Diffstat:
| M | README.md | | | 10 | +++------- |
| M | build.zig | | | 102 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
2 files changed, 69 insertions(+), 43 deletions(-)
diff --git a/README.md b/README.md
@@ -1,14 +1,10 @@
-zig0 aspires to be an interpreter of zig 0.14.0 C backend.
+zig0 aspires to be an interpreter of zig 0.15.1 written in C.
# Testing
-Where the following $CC are supported: `zig`, `clang`, `gcc` and `tcc`. Then:
+Quick test:
- zig build test -Dcc=$CC
-
-Static analysis:
-
- zig build fmt lint
+ zig build
# Debugging tips
diff --git a/build.zig b/build.zig
@@ -36,51 +36,20 @@ const cflags = &[_][]const u8{
//"-D_FORTIFY_SOURCE=2", // consider when optimization flags are enabled
};
+const compilers = &[_][]const u8{ "zig", "clang", "gcc", "tcc" };
+
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const cc = b.option([]const u8, "cc", "C compiler") orelse "zig";
+ const no_exec = b.option(bool, "no-exec", "Compile test binary without running it") orelse false;
const test_step = b.step("test", "Run unit tests");
- const test_mod = b.createModule(.{
- .root_source_file = b.path("test_all.zig"),
- .optimize = optimize,
- .target = target,
- });
- test_mod.addIncludePath(b.path("."));
-
- // TODO(zig 0.16+): remove this if block entirely; keep only the addLibrary branch.
- // Also delete addCObjectsDirectly.
- // Zig 0.15's ELF archive parser fails on archives containing odd-sized objects
- // (off-by-one after 2-byte alignment). This is fixed on zig master/0.16.
- if (comptime builtin.zig_version.order(.{ .major = 0, .minor = 16, .patch = 0 }) == .lt) {
- addCObjectsDirectly(b, test_mod, cc, optimize);
- } else {
- const lib_mod = b.createModule(.{
- .optimize = optimize,
- .target = target,
- .link_libc = true,
- });
- const lib = b.addLibrary(.{
- .name = "tokenizer",
- .root_module = lib_mod,
- });
- addCSources(b, lib.root_module, cc, optimize);
- test_mod.linkLibrary(lib);
- }
-
- const no_exec = b.option(bool, "no-exec", "Compile test binary without running it") orelse false;
- const test_exe = b.addTest(.{ .root_module = test_mod });
- if (no_exec) {
- const install = b.addInstallArtifact(test_exe, .{});
- test_step.dependOn(&install.step);
- } else {
- test_step.dependOn(&b.addRunArtifact(test_exe).step);
- }
+ addTestStep(b, test_step, target, optimize, cc, no_exec);
const fmt_step = b.step("fmt", "clang-format");
- const clang_format = b.addSystemCommand(&.{ "clang-format", "-Werror", "-i" });
+ const clang_format = b.addSystemCommand(&.{ "clang-format", "-i" });
for (all_c_files ++ headers) |f| clang_format.addFileArg(b.path(f));
fmt_step.dependOn(&clang_format.step);
@@ -95,6 +64,7 @@ pub fn build(b: *std.Build) !void {
"-Werror",
});
for (all_c_files) |cfile| clang_analyze.addFileArg(b.path(cfile));
+ clang_analyze.expectExitCode(0);
lint_step.dependOn(&clang_analyze.step);
const gcc_analyze = b.addSystemCommand(&.{
@@ -105,6 +75,7 @@ pub fn build(b: *std.Build) !void {
"/dev/null",
});
for (all_c_files) |cfile| gcc_analyze.addFileArg(b.path(cfile));
+ gcc_analyze.expectExitCode(0);
lint_step.dependOn(&gcc_analyze.step);
const cppcheck = b.addSystemCommand(&.{
@@ -120,7 +91,66 @@ pub fn build(b: *std.Build) !void {
"--suppress=knownConditionTrueFalse", // TODO remove after plumbing is done
});
for (all_c_files) |cfile| cppcheck.addFileArg(b.path(cfile));
+ cppcheck.expectExitCode(0);
lint_step.dependOn(&cppcheck.step);
+
+ const all_step = b.step("all", "Run fmt check, lint, and tests with all compilers");
+ all_step.dependOn(lint_step);
+
+ const fmt_check = b.addSystemCommand(&.{ "clang-format", "--dry-run", "-Werror" });
+ for (all_c_files ++ headers) |f| fmt_check.addFileArg(b.path(f));
+ fmt_check.expectExitCode(0);
+ all_step.dependOn(&fmt_check.step);
+
+ for (compilers) |compiler| {
+ addTestStep(b, all_step, target, optimize, compiler, false);
+ }
+
+ b.default_step = all_step;
+}
+
+fn addTestStep(
+ b: *std.Build,
+ step: *std.Build.Step,
+ target: std.Build.ResolvedTarget,
+ optimize: std.builtin.OptimizeMode,
+ cc: []const u8,
+ no_exec: bool,
+) void {
+ const test_mod = b.createModule(.{
+ .root_source_file = b.path("test_all.zig"),
+ .optimize = optimize,
+ .target = target,
+ });
+ test_mod.addIncludePath(b.path("."));
+
+ // TODO(zig 0.16+): remove this if block entirely; keep only the addLibrary branch.
+ // Also delete addCObjectsDirectly.
+ // Zig 0.15's ELF archive parser fails on archives containing odd-sized objects
+ // (off-by-one after 2-byte alignment). This is fixed on zig master/0.16.
+ if (comptime builtin.zig_version.order(.{ .major = 0, .minor = 16, .patch = 0 }) == .lt) {
+ addCObjectsDirectly(b, test_mod, cc, optimize);
+ } else {
+ const lib_mod = b.createModule(.{
+ .optimize = optimize,
+ .target = target,
+ .link_libc = true,
+ });
+ const lib = b.addLibrary(.{
+ .name = b.fmt("zig0-{s}", .{cc}),
+ .root_module = lib_mod,
+ });
+ addCSources(b, lib.root_module, cc, optimize);
+ test_mod.linkLibrary(lib);
+ }
+
+ const test_exe = b.addTest(.{ .root_module = test_mod });
+ if (no_exec) {
+ const install = b.addInstallArtifact(test_exe, .{});
+ step.dependOn(&install.step);
+ } else {
+ step.dependOn(&b.addRunArtifact(test_exe).step);
+ }
}
fn addCSources(