diff --git a/README.md b/README.md index 4b12629e8e..cbe563aad0 100644 --- 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 index 1f2b340fd0..b66f665e06 100644 --- a/build.zig +++ b/build.zig @@ -36,13 +36,87 @@ 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"); + addTestStep(b, test_step, target, optimize, cc, no_exec); + + const fmt_step = b.step("fmt", "clang-format"); + 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); + + const lint_step = b.step("lint", "Run linters"); + + const clang_analyze = b.addSystemCommand(&.{ + "clang", + "--analyze", + "--analyzer-output", + "text", + "-Wno-unused-command-line-argument", + "-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(&.{ + "gcc", + "--analyzer", + "-Werror", + "-o", + "/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(&.{ + "cppcheck", + "--quiet", + "--error-exitcode=1", + "--check-level=exhaustive", + "--enable=all", + "--suppress=missingIncludeSystem", + "--suppress=checkersReport", + "--suppress=unusedFunction", // TODO remove after plumbing is done + "--suppress=unusedStructMember", // TODO remove after plumbing is done + "--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, @@ -63,64 +137,20 @@ pub fn build(b: *std.Build) !void { .link_libc = true, }); const lib = b.addLibrary(.{ - .name = "tokenizer", + .name = b.fmt("zig0-{s}", .{cc}), .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); + step.dependOn(&install.step); } else { - test_step.dependOn(&b.addRunArtifact(test_exe).step); + step.dependOn(&b.addRunArtifact(test_exe).step); } - - const fmt_step = b.step("fmt", "clang-format"); - const clang_format = b.addSystemCommand(&.{ "clang-format", "-Werror", "-i" }); - for (all_c_files ++ headers) |f| clang_format.addFileArg(b.path(f)); - fmt_step.dependOn(&clang_format.step); - - const lint_step = b.step("lint", "Run linters"); - - const clang_analyze = b.addSystemCommand(&.{ - "clang", - "--analyze", - "--analyzer-output", - "text", - "-Wno-unused-command-line-argument", - "-Werror", - }); - for (all_c_files) |cfile| clang_analyze.addFileArg(b.path(cfile)); - lint_step.dependOn(&clang_analyze.step); - - const gcc_analyze = b.addSystemCommand(&.{ - "gcc", - "--analyzer", - "-Werror", - "-o", - "/dev/null", - }); - for (all_c_files) |cfile| gcc_analyze.addFileArg(b.path(cfile)); - lint_step.dependOn(&gcc_analyze.step); - - const cppcheck = b.addSystemCommand(&.{ - "cppcheck", - "--quiet", - "--error-exitcode=1", - "--check-level=exhaustive", - "--enable=all", - "--suppress=missingIncludeSystem", - "--suppress=checkersReport", - "--suppress=unusedFunction", // TODO remove after plumbing is done - "--suppress=unusedStructMember", // TODO remove after plumbing is done - "--suppress=knownConditionTrueFalse", // TODO remove after plumbing is done - }); - for (all_c_files) |cfile| cppcheck.addFileArg(b.path(cfile)); - lint_step.dependOn(&cppcheck.step); } fn addCSources(