const std = @import("std"); const headers = &[_][]const u8{ "common.h", "ast.h", "parser.h", }; const c_lib_files = &[_][]const u8{ "tokenizer.c", "ast.c", "zig0.c", "parser.c", }; const all_c_files = c_lib_files ++ &[_][]const u8{"main.c"}; const cflags = &[_][]const u8{ "-std=c11", "-Wall", "-Wvla", "-Wextra", "-Werror", "-Wshadow", "-Wswitch", "-Walloca", "-Wformat=2", "-fno-common", "-Wconversion", "-Wuninitialized", "-Wdouble-promotion", "-fstack-protector-all", "-Wimplicit-fallthrough", "-Wno-unused-function", // TODO remove once refactoring is done //"-D_FORTIFY_SOURCE=2", // consider when optimization flags are enabled }; pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const lib = b.addStaticLibrary(.{ .name = "tokenizer", .optimize = optimize, .target = target, }); const cc = b.option([]const u8, "cc", "C compiler") orelse "zig"; if (std.mem.eql(u8, cc, "zig")) lib.addCSourceFiles(.{ .files = c_lib_files, .flags = cflags }) else for (c_lib_files) |cfile| { const cc1 = b.addSystemCommand(&.{cc}); cc1.addArgs(cflags ++ .{"-g"}); cc1.addArg(switch (optimize) { .Debug => "-O0", .ReleaseFast, .ReleaseSafe => "-O3", // ubsan? .ReleaseSmall => "-Os", }); cc1.addArg("-c"); cc1.addFileArg(b.path(cfile)); cc1.addArg("-o"); lib.addObjectFile(cc1.addOutputFileArg(try std.fmt.allocPrint( b.allocator, "{s}.o", .{cfile[0 .. cfile.len - 2]}, ))); } lib.linkLibC(); const test_step = b.step("test", "Run unit tests"); const test_exe = b.addTest(.{ .root_source_file = b.path("test_all.zig"), .optimize = optimize, }); test_exe.linkLibrary(lib); test_exe.addIncludePath(b.path(".")); test_step.dependOn(&b.addRunArtifact(test_exe).step); const lint_step = b.step("lint", "Run linters"); const clang_format = b.addSystemCommand(&.{"clang-format"}); clang_format.addArgs(&.{ "--verbose", "-Werror", "-i" }); for (all_c_files ++ headers) |f| clang_format.addFileArg(b.path(f)); lint_step.dependOn(&clang_format.step); const clang_analyze = b.addSystemCommand(&.{"clang"}); clang_analyze.addArgs(&.{ "--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"}); gcc_analyze.addArgs(&.{ "--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"}); cppcheck.addArgs(&.{ "--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); }