1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn build(b: *std.Build) !void {
5 const test_step = b.step("test", "Test it");
6 b.default_step = test_step;
7
8 if (builtin.os.tag != .windows) return;
9
10 const optimize: std.builtin.Optimize = .debug;
11
12 const lib_gnu = b.addLibrary(.{
13 .linkage = .static,
14 .name = "toargv-gnu",
15 .root_module = b.createModule(.{
16 .root_source_file = b.path("lib.zig"),
17 .target = b.resolveTargetQuery(.{
18 .abi = .gnu,
19 }),
20 .optimize = optimize,
21 }),
22 });
23
24 const verify_gnu = b.addExecutable(.{
25 .name = "verify-gnu",
26 .root_module = b.createModule(.{
27 .root_source_file = null,
28 .target = b.resolveTargetQuery(.{
29 .abi = .gnu,
30 }),
31 .optimize = optimize,
32 }),
33 });
34 verify_gnu.root_module.addCSourceFile(.{
35 .file = b.path("verify.c"),
36 .flags = &.{ "-DUNICODE", "-D_UNICODE" },
37 });
38 verify_gnu.mingw_unicode_entry_point = true;
39 verify_gnu.root_module.linkLibrary(lib_gnu);
40 verify_gnu.root_module.link_libc = true;
41
42 const fuzz = b.addExecutable(.{
43 .name = "fuzz",
44 .root_module = b.createModule(.{
45 .root_source_file = b.path("fuzz.zig"),
46 .target = b.graph.host,
47 .optimize = optimize,
48 }),
49 });
50
51 const fuzz_max_iterations = b.option(u64, "iterations", "The max fuzz iterations (default: 100)") orelse 100;
52 const fuzz_iterations_arg = std.fmt.allocPrint(b.allocator, "{}", .{fuzz_max_iterations}) catch @panic("oom");
53
54 const fuzz_seed = b.option(u64, "seed", "Seed to use for the PRNG (default: random)") orelse seed: {
55 var buf: [8]u8 = undefined;
56 b.graph.io.random(&buf);
57 break :seed std.mem.readInt(u64, &buf, builtin.cpu.arch.endian());
58 };
59 const fuzz_seed_arg = std.fmt.allocPrint(b.allocator, "{}", .{fuzz_seed}) catch @panic("oom");
60
61 const run_gnu = b.addRunArtifact(fuzz);
62 run_gnu.setName("fuzz-gnu");
63 run_gnu.addArtifactArg(verify_gnu);
64 run_gnu.addArgs(&.{ fuzz_iterations_arg, fuzz_seed_arg });
65 run_gnu.expectExitCode(0);
66
67 test_step.dependOn(&run_gnu.step);
68
69 // Only target the MSVC ABI if MSVC/Windows SDK is available
70 const has_msvc = has_msvc: {
71 const sdk = std.zig.WindowsSdk.find(b.allocator, b.graph.io, builtin.cpu.arch, &b.graph.environ_map) catch |err| switch (err) {
72 error.OutOfMemory => @panic("oom"),
73 else => break :has_msvc false,
74 };
75 defer sdk.free(b.allocator);
76 break :has_msvc true;
77 };
78 if (has_msvc) {
79 const lib_msvc = b.addLibrary(.{
80 .linkage = .static,
81 .name = "toargv-msvc",
82 .root_module = b.createModule(.{
83 .root_source_file = b.path("lib.zig"),
84 .target = b.resolveTargetQuery(.{
85 .abi = .msvc,
86 }),
87 .optimize = optimize,
88 }),
89 });
90 const verify_msvc = b.addExecutable(.{
91 .name = "verify-msvc",
92 .root_module = b.createModule(.{
93 .root_source_file = null,
94 .target = b.resolveTargetQuery(.{
95 .abi = .msvc,
96 }),
97 .optimize = optimize,
98 }),
99 });
100 verify_msvc.root_module.addCSourceFile(.{
101 .file = b.path("verify.c"),
102 .flags = &.{ "-DUNICODE", "-D_UNICODE" },
103 });
104 verify_msvc.root_module.linkLibrary(lib_msvc);
105 verify_msvc.root_module.link_libc = true;
106
107 const run_msvc = b.addRunArtifact(fuzz);
108 run_msvc.setName("fuzz-msvc");
109 run_msvc.addArtifactArg(verify_msvc);
110 run_msvc.addArgs(&.{ fuzz_iterations_arg, fuzz_seed_arg });
111 run_msvc.expectExitCode(0);
112
113 test_step.dependOn(&run_msvc.step);
114 }
115}