Skip to content

Commit 4c20f0b

Browse files
committed
introduced proper versioning system
1 parent 124718c commit 4c20f0b

4 files changed

Lines changed: 225 additions & 118 deletions

File tree

build.zig

Lines changed: 219 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,72 @@
11
const std = @import("std");
2+
const afl = @import("zig-afl-kit");
23

34
pub 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

Comments
 (0)