pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const coverage = b.option(bool, "coverage", "Generate a coverage report with kcov") orelse false; const mod = b.addModule("ulzig", .{ .root_source_file = b.path("src/root.zig"), .target = target, }); var exe_mod_options: std.Build.Module.CreateOptions = .{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "ulz", .module = mod }, }, }; if (optimize == .ReleaseSmall) { exe_mod_options.unwind_tables = .none; exe_mod_options.single_threaded = true; } const exe = b.addExecutable(.{ .name = "ulz", .root_module = b.addModule("exe", exe_mod_options), }); if (optimize != .Debug and target.result.os.tag == .linux) { const sstrip = b.addSystemCommand(&.{ "sh", "-c", "cp \"$1\" \"$2\" && sstrip \"$2\"", "sstrip" }); sstrip.addArtifactArg(exe); const stripped = sstrip.addOutputFileArg("ulz"); b.getInstallStep().dependOn(&b.addInstallBinFile(stripped, "ulz").step); } else { b.installArtifact(exe); } const run_step = b.step("run", "Run ulz"); const run_cmd = b.addRunArtifact(exe); run_step.dependOn(&run_cmd.step); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); } const mod_tests = b.addTest(.{ .root_module = mod, .use_llvm = coverage, }); const run_mod_tests = b.addRunArtifact(mod_tests); const exe_tests = b.addTest(.{ .root_module = exe.root_module, .use_llvm = coverage, }); const run_exe_tests = b.addRunArtifact(exe_tests); const tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("test/tests.zig"), .target = b.graph.host, .imports = &.{ .{ .name = "ulz", .module = mod }, }, }), .use_llvm = coverage, }); const run_tests = b.addRunArtifact(tests); const test_step = b.step("test", "Run tests"); test_step.dependOn(&run_mod_tests.step); test_step.dependOn(&run_exe_tests.step); test_step.dependOn(&run_tests.step); if (coverage) { var run_test_steps: std.ArrayList(*std.Build.Step.Run) = .empty; run_test_steps.append(b.allocator, run_mod_tests) catch @panic("OOM"); run_test_steps.append(b.allocator, run_exe_tests) catch @panic("OOM"); run_test_steps.append(b.allocator, run_tests) catch @panic("OOM"); const kcov_bin = b.findProgram(&.{"kcov"}, &.{}) catch "kcov"; const merge_step = std.Build.Step.Run.create(b, "merge coverage"); merge_step.addArgs(&.{ kcov_bin, "--merge" }); merge_step.rename_step_with_output_arg = false; const merged_coverage_output = merge_step.addOutputFileArg("."); for (run_test_steps.items) |step| { step.setName(b.fmt("{s} (collect coverage)", .{step.step.name})); // prepend the kcov exec args const argv = step.argv.toOwnedSlice(b.allocator) catch @panic("OOM"); step.addArgs(&.{ kcov_bin, "--collect-only" }); step.addPrefixedDirectoryArg("--include-pattern=", b.path("src")); merge_step.addDirectoryArg(step.addOutputFileArg(step.producer.?.name)); step.argv.appendSlice(b.allocator, argv) catch @panic("OOM"); } const install_coverage = b.addInstallDirectory(.{ .source_dir = merged_coverage_output, .install_dir = .{ .custom = "coverage" }, .install_subdir = "", }); test_step.dependOn(&install_coverage.step); } } const std = @import("std");