11const std = @import ("std" );
2+ const afl = @import ("zig-afl-kit" );
23
34pub fn build (b : * std.Build ) ! void {
45 const target = b .standardTargetOptions (.{});
56 const optimize = b .standardOptimizeOption (.{});
67
8+ const version = getVersion (b );
9+
710 const scripty = b .dependency ("scripty" , .{});
811 const superhtml = b .addModule ("superhtml" , .{
912 .root_source_file = b .path ("src/root.zig" ),
1013 });
1114 superhtml .addImport ("scripty" , scripty .module ("scripty" ));
1215
16+ const options = b .addOptions ();
17+ const verbose_logging = b .option (bool , "log" , "Enable verbose logging also in release modes" ) orelse false ;
18+ const scopes = b .option ([]const []const u8 , "scope" , "Enable this scope (all scopes are enabled when none is specified through this option), can be used multiple times" ) orelse &[0 ][]const u8 {};
19+ options .addOption (bool , "verbose_logging" , verbose_logging );
20+ options .addOption ([]const []const u8 , "enabled_scopes" , scopes );
21+ options .addOption ([]const u8 , "version" , version .string ());
22+ options .addOption (Version .Kind , "version_kind" , version );
23+
24+ const folders = b .dependency ("known-folders" , .{});
25+ const lsp = b .dependency ("zig-lsp-kit" , .{});
26+
27+ setupCliTool (b , target , optimize , options , superhtml , folders , lsp );
28+ setupWasmStep (b , optimize , options , superhtml , lsp );
29+ setupFuzzStep (b , target , superhtml );
30+ setupCheckStep (b , target , optimize , options , superhtml , folders , lsp );
31+ if (version == .tag ) {
32+ setupReleaseStep (b , options , superhtml , folders , lsp );
33+ }
34+ }
35+
36+ fn setupCheckStep (
37+ b : * std.Build ,
38+ target : std.Build.ResolvedTarget ,
39+ optimize : std.builtin.OptimizeMode ,
40+ options : * std.Build.Step.Options ,
41+ superhtml : * std.Build.Module ,
42+ folders : * std.Build.Dependency ,
43+ lsp : * std.Build.Dependency ,
44+ ) void {
45+ const super_cli_check = b .addExecutable (.{
46+ .name = "superhtml" ,
47+ .root_source_file = b .path ("src/cli.zig" ),
48+ .target = target ,
49+ .optimize = optimize ,
50+ });
51+
52+ super_cli_check .root_module .addImport ("superhtml" , superhtml );
53+ super_cli_check .root_module .addImport (
54+ "known-folders" ,
55+ folders .module ("known-folders" ),
56+ );
57+ super_cli_check .root_module .addImport ("lsp" , lsp .module ("lsp" ));
58+ super_cli_check .root_module .addOptions ("build_options" , options );
59+
60+ const check = b .step ("check" , "Check if the SuperHTML CLI compiles" );
61+ check .dependOn (& super_cli_check .step );
62+ }
63+ fn setupTestStep (
64+ b : * std.Build ,
65+ target : std.Build.ResolvedTarget ,
66+ superhtml : * std.Build.Module ,
67+ ) void {
68+ const test_step = b .step ("test" , "Run unit tests" );
69+
1370 const unit_tests = b .addTest (.{
1471 .root_source_file = b .path ("src/root.zig" ),
1572 .target = target ,
@@ -21,9 +78,77 @@ pub fn build(b: *std.Build) !void {
2178 unit_tests .root_module .addImport ("superhtml" , superhtml );
2279
2380 const run_unit_tests = b .addRunArtifact (unit_tests );
24- const test_step = b .step ("test" , "Run unit tests" );
2581 test_step .dependOn (& run_unit_tests .step );
2682
83+ const fuzz_tests = b .addTest (.{
84+ .root_source_file = b .path ("src/fuzz.zig" ),
85+ .target = target ,
86+ .optimize = .Debug ,
87+ // .strip = true,
88+ // .filter = "nesting",
89+ });
90+
91+ fuzz_tests .root_module .addImport ("superhtml" , superhtml );
92+ const run_fuzz_tests = b .addRunArtifact (fuzz_tests );
93+ test_step .dependOn (& run_fuzz_tests .step );
94+ }
95+
96+ fn setupFuzzStep (
97+ b : * std.Build ,
98+ target : std.Build.ResolvedTarget ,
99+ superhtml : * std.Build.Module ,
100+ ) void {
101+ const fuzz = b .step (
102+ "fuzz" ,
103+ "Generate an executable for AFL++ (persistent mode) plus extra tooling" ,
104+ );
105+ const afl_obj = b .addObject (.{
106+ .name = "superfuzz-afl" ,
107+ .root_source_file = b .path ("src/fuzz/afl.zig" ),
108+ .target = target ,
109+ .optimize = .Debug ,
110+ .single_threaded = true ,
111+ });
112+
113+ afl_obj .root_module .addImport ("superhtml" , superhtml );
114+ afl_obj .root_module .stack_check = false ; // not linking with compiler-rt
115+ afl_obj .root_module .link_libc = true ; // afl runtime depends on libc
116+
117+ const afl_fuzz = afl .addInstrumentedExe (b , afl_obj );
118+ fuzz .dependOn (& b .addInstallFile (afl_fuzz , "superfuzz-afl" ).step );
119+
120+ const super_fuzz = b .addExecutable (.{
121+ .name = "superfuzz" ,
122+ .root_source_file = b .path ("src/fuzz.zig" ),
123+ .target = target ,
124+ .optimize = .Debug ,
125+ .single_threaded = true ,
126+ });
127+
128+ super_fuzz .root_module .addImport ("superhtml" , superhtml );
129+ fuzz .dependOn (& b .addInstallArtifact (super_fuzz , .{}).step );
130+
131+ const supergen = b .addExecutable (.{
132+ .name = "supergen" ,
133+ .root_source_file = b .path ("src/fuzz/astgen.zig" ),
134+ .target = target ,
135+ .optimize = .Debug ,
136+ .single_threaded = true ,
137+ });
138+
139+ supergen .root_module .addImport ("superhtml" , superhtml );
140+ fuzz .dependOn (& b .addInstallArtifact (supergen , .{}).step );
141+ }
142+
143+ fn setupCliTool (
144+ b : * std.Build ,
145+ target : std.Build.ResolvedTarget ,
146+ optimize : std.builtin.OptimizeMode ,
147+ options : * std.Build.Step.Options ,
148+ superhtml : * std.Build.Module ,
149+ folders : * std.Build.Dependency ,
150+ lsp : * std.Build.Dependency ,
151+ ) void {
27152 const super_cli = b .addExecutable (.{
28153 .name = "superhtml" ,
29154 .root_source_file = b .path ("src/cli.zig" ),
@@ -32,15 +157,6 @@ pub fn build(b: *std.Build) !void {
32157 .single_threaded = true ,
33158 });
34159
35- const verbose_logging = b .option (bool , "log" , "Enable verbose logging also in release modes" ) orelse false ;
36- const scopes = b .option ([]const []const u8 , "scope" , "Enable this scope (all scopes are enabled when none is specified through this option), can be used multiple times" ) orelse &[0 ][]const u8 {};
37- const options = b .addOptions ();
38- options .addOption (bool , "verbose_logging" , verbose_logging );
39- options .addOption ([]const []const u8 , "enabled_scopes" , scopes );
40-
41- const folders = b .dependency ("known-folders" , .{});
42- const lsp = b .dependency ("zig-lsp-kit" , .{});
43-
44160 super_cli .root_module .addImport ("superhtml" , superhtml );
45161 super_cli .root_module .addImport (
46162 "known-folders" ,
@@ -55,26 +171,49 @@ pub fn build(b: *std.Build) !void {
55171 run_exe_step .dependOn (& run_exe .step );
56172
57173 b .installArtifact (super_cli );
174+ }
58175
59- const super_cli_check = b .addExecutable (.{
176+ fn setupWasmStep (
177+ b : * std.Build ,
178+ optimize : std.builtin.OptimizeMode ,
179+ options : * std.Build.Step.Options ,
180+ superhtml : * std.Build.Module ,
181+ lsp : * std.Build.Dependency ,
182+ ) void {
183+ const wasm = b .step ("wasm" , "Generate a WASM build of the SuperHTML LSP for VSCode" );
184+ const super_wasm_lsp = b .addExecutable (.{
60185 .name = "superhtml" ,
61- .root_source_file = b .path ("src/cli.zig" ),
62- .target = target ,
186+ .root_source_file = b .path ("src/wasm.zig" ),
187+ .target = b .resolveTargetQuery (.{
188+ .cpu_arch = .wasm32 ,
189+ .os_tag = .wasi ,
190+ }),
63191 .optimize = optimize ,
192+ .single_threaded = true ,
193+ .link_libc = false ,
64194 });
65195
66- super_cli_check .root_module .addImport ("superhtml" , superhtml );
67- super_cli_check .root_module .addImport (
68- "known-folders" ,
69- folders .module ("known-folders" ),
70- );
71- super_cli_check .root_module .addImport ("lsp" , lsp .module ("lsp" ));
72- super_cli_check .root_module .addOptions ("build_options" , options );
196+ super_wasm_lsp .root_module .addImport ("superhtml" , superhtml );
197+ super_wasm_lsp .root_module .addImport ("lsp" , lsp .module ("lsp" ));
198+ super_wasm_lsp .root_module .addOptions ("build_options" , options );
73199
74- const check = b .step ("check" , "Check if the SuperHTML CLI compiles" );
75- check .dependOn (& super_cli_check .step );
200+ const target_output = b .addInstallArtifact (super_wasm_lsp , .{
201+ .dest_dir = .{ .override = .{ .custom = "" } },
202+ });
203+ wasm .dependOn (& target_output .step );
204+ }
76205
77- const release_step = b .step ("release" , "Create releases for the SuperHTML CLI" );
206+ fn setupReleaseStep (
207+ b : * std.Build ,
208+ options : * std.Build.Step.Options ,
209+ superhtml : * std.Build.Module ,
210+ folders : * std.Build.Dependency ,
211+ lsp : * std.Build.Dependency ,
212+ ) void {
213+ const release_step = b .step (
214+ "release" ,
215+ "Create releases for the SuperHTML CLI" ,
216+ );
78217 const targets : []const std.Target.Query = &.{
79218 .{ .cpu_arch = .aarch64 , .os_tag = .macos },
80219 .{ .cpu_arch = .aarch64 , .os_tag = .linux },
@@ -105,103 +244,71 @@ pub fn build(b: *std.Build) !void {
105244 const target_output = b .addInstallArtifact (super_exe_release , .{
106245 .dest_dir = .{
107246 .override = .{
108- .custom = try t .zigTriple (b .allocator ),
247+ .custom = t .zigTriple (b .allocator ) catch unreachable ,
109248 },
110249 },
111250 });
112251
113252 release_step .dependOn (& target_output .step );
114253 }
254+ }
115255
116- const super_wasm_lsp = b .addExecutable (.{
117- .name = "superhtml" ,
118- .root_source_file = b .path ("src/wasm.zig" ),
119- .target = b .resolveTargetQuery (.{
120- .cpu_arch = .wasm32 ,
121- .os_tag = .wasi ,
122- }),
123- .optimize = optimize ,
124- .single_threaded = true ,
125- .link_libc = false ,
126- });
127-
128- super_wasm_lsp .root_module .addImport ("superhtml" , superhtml );
129- super_wasm_lsp .root_module .addImport ("lsp" , lsp .module ("lsp" ));
130- super_wasm_lsp .root_module .addOptions ("build_options" , options );
131-
132- const wasm = b .step ("wasm" , "Generate a WASM build of the SuperHTML LSP for VSCode" );
133- const target_output = b .addInstallArtifact (super_wasm_lsp , .{
134- .dest_dir = .{ .override = .{ .custom = "" } },
135- });
136- wasm .dependOn (& target_output .step );
137-
138- const afl_fuzz_name = b .fmt ("superfuzz-afl{s}" , .{target .result .exeFileExt ()});
139- const afl_fuzz = b .addStaticLibrary (.{
140- .name = afl_fuzz_name ,
141- .root_source_file = b .path ("src/fuzz/afl.zig" ),
142- // .target = b.resolveTargetQuery(.{ .ofmt = .c }),
143- .target = target ,
144- .optimize = .Debug ,
145- .single_threaded = true ,
146- });
147-
148- afl_fuzz .root_module .addImport ("superhtml" , superhtml );
149- afl_fuzz .root_module .stack_check = false ; // not linking with compiler-rt
150- afl_fuzz .root_module .link_libc = true ; // afl runtime depends on libc
151- _ = afl_fuzz .getEmittedBin (); // hack around build system bug
152-
153- const afl_clang_fast_path = b .findProgram (
154- &.{ "afl-clang-fast" , "afl-clang" },
155- if (b .option ([]const u8 , "afl-path" , "Path to AFLplusplus" )) | afl_path |
156- &.{afl_path }
157- else
158- &.{},
159- ) catch "afl-clang-fast" ;
160-
161- const fuzz = b .step ("fuzz" , "Generate an executable for AFL++ (persistent mode) plus extra tooling" );
162- const run_afl_clang_fast = b .addSystemCommand (&.{
163- afl_clang_fast_path ,
164- "-o" ,
165- });
166-
167- const prog_exe = run_afl_clang_fast .addOutputFileArg (afl_fuzz_name );
168- run_afl_clang_fast .addFileArg (b .path ("src/fuzz/afl.c" ));
169- // run_afl_clang_fast.addFileArg(afl_fuzz.getEmittedBin());
170- // run_afl_clang_fast.addArg("-I/Users/kristoff/zig/0.13.0/files/lib/");
171- run_afl_clang_fast .addFileArg (afl_fuzz .getEmittedLlvmBc ());
172- fuzz .dependOn (& b .addInstallBinFile (prog_exe , afl_fuzz_name ).step );
173-
174- const super_fuzz = b .addExecutable (.{
175- .name = "superfuzz" ,
176- .root_source_file = b .path ("src/fuzz.zig" ),
177- .target = target ,
178- .optimize = .Debug ,
179- .single_threaded = true ,
180- });
181-
182- super_fuzz .root_module .addImport ("superhtml" , superhtml );
183- fuzz .dependOn (& b .addInstallArtifact (super_fuzz , .{}).step );
184-
185- const supergen = b .addExecutable (.{
186- .name = "supergen" ,
187- .root_source_file = b .path ("src/fuzz/astgen.zig" ),
188- .target = target ,
189- .optimize = .Debug ,
190- .single_threaded = true ,
191- });
256+ const Version = union (Kind ) {
257+ tag : []const u8 ,
258+ commit : []const u8 ,
259+ // not in a git repo
260+ unknown ,
192261
193- supergen .root_module .addImport ("superhtml" , superhtml );
194- fuzz .dependOn (& b .addInstallArtifact (supergen , .{}).step );
262+ pub const Kind = enum { tag , commit , unknown };
195263
196- const fuzz_tests = b .addTest (.{
197- .root_source_file = b .path ("src/fuzz.zig" ),
198- .target = target ,
199- .optimize = .Debug ,
200- // .strip = true,
201- // .filter = "nesting",
202- });
264+ pub fn string (v : Version ) []const u8 {
265+ return switch (v ) {
266+ .tag , .commit = > | tc | tc ,
267+ .unknown = > "unknown" ,
268+ };
269+ }
270+ };
271+ fn getVersion (b : * std.Build ) Version {
272+ const git_path = b .findProgram (&.{"git" }, &.{}) catch return .unknown ;
273+ const git_describe = std .mem .trim (
274+ u8 ,
275+ b .run (&[_ ][]const u8 {
276+ git_path , "-C" ,
277+ b .build_root .path .? , "describe" ,
278+ "--match" , "*.*.*" ,
279+ "--tags" ,
280+ }),
281+ " \n \r " ,
282+ );
203283
204- fuzz_tests .root_module .addImport ("superhtml" , superhtml );
205- const run_fuzz_tests = b .addRunArtifact (fuzz_tests );
206- test_step .dependOn (& run_fuzz_tests .step );
284+ switch (std .mem .count (u8 , git_describe , "-" )) {
285+ 0 = > return .{ .tag = git_describe },
286+ 2 = > {
287+ // Untagged development build (e.g. 0.8.0-684-gbbe2cca1a).
288+ var it = std .mem .split (u8 , git_describe , "-" );
289+ const tagged_ancestor = it .next () orelse unreachable ;
290+ const commit_height = it .next () orelse unreachable ;
291+ const commit_id = it .next () orelse unreachable ;
292+
293+ // Check that the commit hash is prefixed with a 'g'
294+ // (it's a Git convention)
295+ if (commit_id .len < 1 or commit_id [0 ] != 'g' ) {
296+ std .debug .panic ("Unexpected `git describe` output: {s}\n " , .{git_describe });
297+ }
298+
299+ // The version is reformatted in accordance with
300+ // the https://semver.org specification.
301+ return .{
302+ .commit = b .fmt ("{s}-dev.{s}+{s}" , .{
303+ tagged_ancestor ,
304+ commit_height ,
305+ commit_id [1.. ],
306+ }),
307+ };
308+ },
309+ else = > std .debug .panic (
310+ "Unexpected `git describe` output: {s}\n " ,
311+ .{git_describe },
312+ ),
313+ }
207314}
0 commit comments