Skip to content

Commit

Permalink
introduced proper versioning system
Browse files Browse the repository at this point in the history
  • Loading branch information
kristoff-it committed Jul 23, 2024
1 parent 124718c commit 4c20f0b
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 118 deletions.
331 changes: 219 additions & 112 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,15 +1,72 @@
const std = @import("std");
const afl = @import("zig-afl-kit");

pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const version = getVersion(b);

const scripty = b.dependency("scripty", .{});
const superhtml = b.addModule("superhtml", .{
.root_source_file = b.path("src/root.zig"),
});
superhtml.addImport("scripty", scripty.module("scripty"));

const options = b.addOptions();
const verbose_logging = b.option(bool, "log", "Enable verbose logging also in release modes") orelse false;
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{};
options.addOption(bool, "verbose_logging", verbose_logging);
options.addOption([]const []const u8, "enabled_scopes", scopes);
options.addOption([]const u8, "version", version.string());
options.addOption(Version.Kind, "version_kind", version);

const folders = b.dependency("known-folders", .{});
const lsp = b.dependency("zig-lsp-kit", .{});

setupCliTool(b, target, optimize, options, superhtml, folders, lsp);
setupWasmStep(b, optimize, options, superhtml, lsp);
setupFuzzStep(b, target, superhtml);
setupCheckStep(b, target, optimize, options, superhtml, folders, lsp);
if (version == .tag) {
setupReleaseStep(b, options, superhtml, folders, lsp);
}
}

fn setupCheckStep(
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
options: *std.Build.Step.Options,
superhtml: *std.Build.Module,
folders: *std.Build.Dependency,
lsp: *std.Build.Dependency,
) void {
const super_cli_check = b.addExecutable(.{
.name = "superhtml",
.root_source_file = b.path("src/cli.zig"),
.target = target,
.optimize = optimize,
});

super_cli_check.root_module.addImport("superhtml", superhtml);
super_cli_check.root_module.addImport(
"known-folders",
folders.module("known-folders"),
);
super_cli_check.root_module.addImport("lsp", lsp.module("lsp"));
super_cli_check.root_module.addOptions("build_options", options);

const check = b.step("check", "Check if the SuperHTML CLI compiles");
check.dependOn(&super_cli_check.step);
}
fn setupTestStep(
b: *std.Build,
target: std.Build.ResolvedTarget,
superhtml: *std.Build.Module,
) void {
const test_step = b.step("test", "Run unit tests");

const unit_tests = b.addTest(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
Expand All @@ -21,9 +78,77 @@ pub fn build(b: *std.Build) !void {
unit_tests.root_module.addImport("superhtml", superhtml);

const run_unit_tests = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);

const fuzz_tests = b.addTest(.{
.root_source_file = b.path("src/fuzz.zig"),
.target = target,
.optimize = .Debug,
// .strip = true,
// .filter = "nesting",
});

fuzz_tests.root_module.addImport("superhtml", superhtml);
const run_fuzz_tests = b.addRunArtifact(fuzz_tests);
test_step.dependOn(&run_fuzz_tests.step);
}

fn setupFuzzStep(
b: *std.Build,
target: std.Build.ResolvedTarget,
superhtml: *std.Build.Module,
) void {
const fuzz = b.step(
"fuzz",
"Generate an executable for AFL++ (persistent mode) plus extra tooling",
);
const afl_obj = b.addObject(.{
.name = "superfuzz-afl",
.root_source_file = b.path("src/fuzz/afl.zig"),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});

afl_obj.root_module.addImport("superhtml", superhtml);
afl_obj.root_module.stack_check = false; // not linking with compiler-rt
afl_obj.root_module.link_libc = true; // afl runtime depends on libc

const afl_fuzz = afl.addInstrumentedExe(b, afl_obj);
fuzz.dependOn(&b.addInstallFile(afl_fuzz, "superfuzz-afl").step);

const super_fuzz = b.addExecutable(.{
.name = "superfuzz",
.root_source_file = b.path("src/fuzz.zig"),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});

super_fuzz.root_module.addImport("superhtml", superhtml);
fuzz.dependOn(&b.addInstallArtifact(super_fuzz, .{}).step);

const supergen = b.addExecutable(.{
.name = "supergen",
.root_source_file = b.path("src/fuzz/astgen.zig"),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});

supergen.root_module.addImport("superhtml", superhtml);
fuzz.dependOn(&b.addInstallArtifact(supergen, .{}).step);
}

fn setupCliTool(
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
options: *std.Build.Step.Options,
superhtml: *std.Build.Module,
folders: *std.Build.Dependency,
lsp: *std.Build.Dependency,
) void {
const super_cli = b.addExecutable(.{
.name = "superhtml",
.root_source_file = b.path("src/cli.zig"),
Expand All @@ -32,15 +157,6 @@ pub fn build(b: *std.Build) !void {
.single_threaded = true,
});

const verbose_logging = b.option(bool, "log", "Enable verbose logging also in release modes") orelse false;
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{};
const options = b.addOptions();
options.addOption(bool, "verbose_logging", verbose_logging);
options.addOption([]const []const u8, "enabled_scopes", scopes);

const folders = b.dependency("known-folders", .{});
const lsp = b.dependency("zig-lsp-kit", .{});

super_cli.root_module.addImport("superhtml", superhtml);
super_cli.root_module.addImport(
"known-folders",
Expand All @@ -55,26 +171,49 @@ pub fn build(b: *std.Build) !void {
run_exe_step.dependOn(&run_exe.step);

b.installArtifact(super_cli);
}

const super_cli_check = b.addExecutable(.{
fn setupWasmStep(
b: *std.Build,
optimize: std.builtin.OptimizeMode,
options: *std.Build.Step.Options,
superhtml: *std.Build.Module,
lsp: *std.Build.Dependency,
) void {
const wasm = b.step("wasm", "Generate a WASM build of the SuperHTML LSP for VSCode");
const super_wasm_lsp = b.addExecutable(.{
.name = "superhtml",
.root_source_file = b.path("src/cli.zig"),
.target = target,
.root_source_file = b.path("src/wasm.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.os_tag = .wasi,
}),
.optimize = optimize,
.single_threaded = true,
.link_libc = false,
});

super_cli_check.root_module.addImport("superhtml", superhtml);
super_cli_check.root_module.addImport(
"known-folders",
folders.module("known-folders"),
);
super_cli_check.root_module.addImport("lsp", lsp.module("lsp"));
super_cli_check.root_module.addOptions("build_options", options);
super_wasm_lsp.root_module.addImport("superhtml", superhtml);
super_wasm_lsp.root_module.addImport("lsp", lsp.module("lsp"));
super_wasm_lsp.root_module.addOptions("build_options", options);

const check = b.step("check", "Check if the SuperHTML CLI compiles");
check.dependOn(&super_cli_check.step);
const target_output = b.addInstallArtifact(super_wasm_lsp, .{
.dest_dir = .{ .override = .{ .custom = "" } },
});
wasm.dependOn(&target_output.step);
}

const release_step = b.step("release", "Create releases for the SuperHTML CLI");
fn setupReleaseStep(
b: *std.Build,
options: *std.Build.Step.Options,
superhtml: *std.Build.Module,
folders: *std.Build.Dependency,
lsp: *std.Build.Dependency,
) void {
const release_step = b.step(
"release",
"Create releases for the SuperHTML CLI",
);
const targets: []const std.Target.Query = &.{
.{ .cpu_arch = .aarch64, .os_tag = .macos },
.{ .cpu_arch = .aarch64, .os_tag = .linux },
Expand Down Expand Up @@ -105,103 +244,71 @@ pub fn build(b: *std.Build) !void {
const target_output = b.addInstallArtifact(super_exe_release, .{
.dest_dir = .{
.override = .{
.custom = try t.zigTriple(b.allocator),
.custom = t.zigTriple(b.allocator) catch unreachable,
},
},
});

release_step.dependOn(&target_output.step);
}
}

const super_wasm_lsp = b.addExecutable(.{
.name = "superhtml",
.root_source_file = b.path("src/wasm.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.os_tag = .wasi,
}),
.optimize = optimize,
.single_threaded = true,
.link_libc = false,
});

super_wasm_lsp.root_module.addImport("superhtml", superhtml);
super_wasm_lsp.root_module.addImport("lsp", lsp.module("lsp"));
super_wasm_lsp.root_module.addOptions("build_options", options);

const wasm = b.step("wasm", "Generate a WASM build of the SuperHTML LSP for VSCode");
const target_output = b.addInstallArtifact(super_wasm_lsp, .{
.dest_dir = .{ .override = .{ .custom = "" } },
});
wasm.dependOn(&target_output.step);

const afl_fuzz_name = b.fmt("superfuzz-afl{s}", .{target.result.exeFileExt()});
const afl_fuzz = b.addStaticLibrary(.{
.name = afl_fuzz_name,
.root_source_file = b.path("src/fuzz/afl.zig"),
// .target = b.resolveTargetQuery(.{ .ofmt = .c }),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});

afl_fuzz.root_module.addImport("superhtml", superhtml);
afl_fuzz.root_module.stack_check = false; // not linking with compiler-rt
afl_fuzz.root_module.link_libc = true; // afl runtime depends on libc
_ = afl_fuzz.getEmittedBin(); // hack around build system bug

const afl_clang_fast_path = b.findProgram(
&.{ "afl-clang-fast", "afl-clang" },
if (b.option([]const u8, "afl-path", "Path to AFLplusplus")) |afl_path|
&.{afl_path}
else
&.{},
) catch "afl-clang-fast";

const fuzz = b.step("fuzz", "Generate an executable for AFL++ (persistent mode) plus extra tooling");
const run_afl_clang_fast = b.addSystemCommand(&.{
afl_clang_fast_path,
"-o",
});

const prog_exe = run_afl_clang_fast.addOutputFileArg(afl_fuzz_name);
run_afl_clang_fast.addFileArg(b.path("src/fuzz/afl.c"));
// run_afl_clang_fast.addFileArg(afl_fuzz.getEmittedBin());
// run_afl_clang_fast.addArg("-I/Users/kristoff/zig/0.13.0/files/lib/");
run_afl_clang_fast.addFileArg(afl_fuzz.getEmittedLlvmBc());
fuzz.dependOn(&b.addInstallBinFile(prog_exe, afl_fuzz_name).step);

const super_fuzz = b.addExecutable(.{
.name = "superfuzz",
.root_source_file = b.path("src/fuzz.zig"),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});

super_fuzz.root_module.addImport("superhtml", superhtml);
fuzz.dependOn(&b.addInstallArtifact(super_fuzz, .{}).step);

const supergen = b.addExecutable(.{
.name = "supergen",
.root_source_file = b.path("src/fuzz/astgen.zig"),
.target = target,
.optimize = .Debug,
.single_threaded = true,
});
const Version = union(Kind) {
tag: []const u8,
commit: []const u8,
// not in a git repo
unknown,

supergen.root_module.addImport("superhtml", superhtml);
fuzz.dependOn(&b.addInstallArtifact(supergen, .{}).step);
pub const Kind = enum { tag, commit, unknown };

const fuzz_tests = b.addTest(.{
.root_source_file = b.path("src/fuzz.zig"),
.target = target,
.optimize = .Debug,
// .strip = true,
// .filter = "nesting",
});
pub fn string(v: Version) []const u8 {
return switch (v) {
.tag, .commit => |tc| tc,
.unknown => "unknown",
};
}
};
fn getVersion(b: *std.Build) Version {
const git_path = b.findProgram(&.{"git"}, &.{}) catch return .unknown;
const git_describe = std.mem.trim(
u8,
b.run(&[_][]const u8{
git_path, "-C",
b.build_root.path.?, "describe",
"--match", "*.*.*",
"--tags",
}),
" \n\r",
);

fuzz_tests.root_module.addImport("superhtml", superhtml);
const run_fuzz_tests = b.addRunArtifact(fuzz_tests);
test_step.dependOn(&run_fuzz_tests.step);
switch (std.mem.count(u8, git_describe, "-")) {
0 => return .{ .tag = git_describe },
2 => {
// Untagged development build (e.g. 0.8.0-684-gbbe2cca1a).
var it = std.mem.split(u8, git_describe, "-");
const tagged_ancestor = it.next() orelse unreachable;
const commit_height = it.next() orelse unreachable;
const commit_id = it.next() orelse unreachable;

// Check that the commit hash is prefixed with a 'g'
// (it's a Git convention)
if (commit_id.len < 1 or commit_id[0] != 'g') {
std.debug.panic("Unexpected `git describe` output: {s}\n", .{git_describe});
}

// The version is reformatted in accordance with
// the https://semver.org specification.
return .{
.commit = b.fmt("{s}-dev.{s}+{s}", .{
tagged_ancestor,
commit_height,
commit_id[1..],
}),
};
},
else => std.debug.panic(
"Unexpected `git describe` output: {s}\n",
.{git_describe},
),
}
}
Loading

0 comments on commit 4c20f0b

Please sign in to comment.