diff options
author | Chris Boesch <chrboesch@noreply.codeberg.org> | 2023-04-07 18:24:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-07 18:24:42 +0200 |
commit | e242d821baadbb9ab895f8eacac2e8e72589dffa (patch) | |
tree | c6f59c28b8abd9b92a2183ac2078d6c83d869904 /build.zig | |
parent | 8bf719e5e22dacccf68916455b7634b7b04453a0 (diff) | |
parent | ddc835762c1276c781295164a2bb3e42b35670df (diff) |
Merge pull request #212 from perillo/improve-build
build: make the logo a build step
Diffstat (limited to 'build.zig')
-rw-r--r-- | build.zig | 180 |
1 files changed, 107 insertions, 73 deletions
@@ -1,15 +1,13 @@ const std = @import("std"); const builtin = @import("builtin"); -const Builder = std.build.Builder; -const Step = std.build.Step; +const compat = @import("src/compat.zig"); + +const Build = compat.Build; +const Step = compat.build.Step; + const assert = std.debug.assert; const print = std.debug.print; -// When changing this version, be sure to also update README.md in two places: -// 1) Getting Started -// 2) Version Changes -const needed_version = std.SemanticVersion.parse("0.11.0-dev.2157") catch unreachable; - const Exercise = struct { /// main_file must have the format key_name.zig. /// The key will be used as a shorthand to build @@ -53,6 +51,11 @@ const Exercise = struct { while (self.main_file[start_index] == '0') start_index += 1; return self.main_file[start_index..end_index.?]; } + + /// Returns the exercise key as an integer. + pub fn number(self: Exercise) usize { + return std.fmt.parseInt(usize, self.key(), 10) catch unreachable; + } }; const exercises = [_]Exercise{ @@ -493,44 +496,8 @@ const exercises = [_]Exercise{ }, }; -/// Check the zig version to make sure it can compile the examples properly. -/// This will compile with Zig 0.6.0 and later. -fn checkVersion() bool { - if (!@hasDecl(builtin, "zig_version")) { - return false; - } - - const version = builtin.zig_version; - const order = version.order(needed_version); - return order != .lt; -} - -pub fn build(b: *Builder) !void { - // Use a comptime branch for the version check. - // If this fails, code after this block is not compiled. - // It is parsed though, so versions of zig from before 0.6.0 - // cannot do the version check and will just fail to compile. - // We could fix this by moving the ziglings code to a separate file, - // but 0.5.0 was a long time ago, it is unlikely that anyone who - // attempts these exercises is still using it. - if (comptime !checkVersion()) { - // very old versions of Zig used warn instead of print. - const stderrPrintFn = if (@hasDecl(std.debug, "print")) std.debug.print else std.debug.warn; - stderrPrintFn( - \\ERROR: Sorry, it looks like your version of zig is too old. :-( - \\ - \\Ziglings requires development build - \\ - \\ {} - \\ - \\or higher. Please download a development ("master") build from - \\ - \\ https://ziglang.org/download/ - \\ - \\ - , .{needed_version}); - std.os.exit(0); - } +pub fn build(b: *Build) !void { + if (!compat.is_compatible) compat.die(); use_color_escapes = false; if (std.io.getStdErr().supportsAnsiEscapeCodes()) { @@ -571,51 +538,88 @@ pub fn build(b: *Builder) !void { \\ \\ ; - const header_step = b.step("info", logo); - print("{s}\n", .{logo}); - const verify_all = b.step("ziglings", "Check all ziglings"); - verify_all.dependOn(header_step); - b.default_step = verify_all; + const use_healed = b.option(bool, "healed", "Run exercises from patches/healed") orelse false; + const exno: ?usize = b.option(usize, "n", "Select exercise"); - var prev_chain_verify = verify_all; + const header_step = PrintStep.create(b, logo, std.io.getStdErr()); - const use_healed = b.option(bool, "healed", "Run exercises from patches/healed") orelse false; + if (exno) |i| { + const ex = blk: { + for (exercises) |ex| { + if (ex.number() == i) break :blk ex; + } + + print("unknown exercise number: {}\n", .{i}); + std.os.exit(1); + }; - for (exercises) |ex| { const base_name = ex.baseName(); const file_path = std.fs.path.join(b.allocator, &[_][]const u8{ if (use_healed) "patches/healed" else "exercises", ex.main_file, }) catch unreachable; - const build_step = b.addExecutable(.{ .name = base_name, .root_source_file = .{ .path = file_path } }); + const build_step = b.addExecutable(.{ .name = base_name, .root_source_file = .{ .path = file_path } }); build_step.install(); + const run_step = build_step.run(); + + const test_step = b.step("test", b.fmt("Run {s} without checking output", .{ex.main_file})); + test_step.dependOn(&run_step.step); + + const install_step = b.step("install", b.fmt("Install {s} to prefix path", .{ex.main_file})); + install_step.dependOn(b.getInstallStep()); + + const uninstall_step = b.step("uninstall", b.fmt("Uninstall {s} from prefix path", .{ex.main_file})); + uninstall_step.dependOn(b.getUninstallStep()); + const verify_step = ZiglingStep.create(b, ex, use_healed); - const key = ex.key(); + const zigling_step = b.step("zigling", b.fmt("Check the solution of {s}", .{ex.main_file})); + zigling_step.dependOn(&verify_step.step); + b.default_step = zigling_step; - const named_test = b.step(b.fmt("{s}_test", .{key}), b.fmt("Run {s} without checking output", .{ex.main_file})); - const run_step = build_step.run(); - named_test.dependOn(&run_step.step); + const start_step = b.step("start", b.fmt("Check all solutions starting at {s}", .{ex.main_file})); - const named_install = b.step(b.fmt("{s}_install", .{key}), b.fmt("Install {s} to zig-cache/bin", .{ex.main_file})); - named_install.dependOn(&build_step.install_step.?.step); + var prev_step = verify_step; + for (exercises) |exn| { + const n = exn.number(); + if (n > i) { + const verify_stepn = ZiglingStep.create(b, exn, use_healed); + verify_stepn.step.dependOn(&prev_step.step); - const named_verify = b.step(key, b.fmt("Check {s} only", .{ex.main_file})); - named_verify.dependOn(&verify_step.step); + prev_step = verify_stepn; + } + } + start_step.dependOn(&prev_step.step); - const chain_verify = b.allocator.create(Step) catch unreachable; - chain_verify.* = Step.init(Step.Options{ .id = .custom, .name = b.fmt("chain {s}", .{key}), .owner = b }); - chain_verify.dependOn(&verify_step.step); + return; + } - const named_chain = b.step(b.fmt("{s}_start", .{key}), b.fmt("Check all solutions starting at {s}", .{ex.main_file})); - named_chain.dependOn(header_step); - named_chain.dependOn(chain_verify); + const ziglings_step = b.step("ziglings", "Check all ziglings"); + ziglings_step.dependOn(&header_step.step); + b.default_step = ziglings_step; - prev_chain_verify.dependOn(chain_verify); - prev_chain_verify = chain_verify; + var prev_step: *Step = undefined; + for (exercises, 0..) |ex, i| { + const base_name = ex.baseName(); + const file_path = std.fs.path.join(b.allocator, &[_][]const u8{ + if (use_healed) "patches/healed" else "exercises", ex.main_file, + }) catch unreachable; + + const build_step = b.addExecutable(.{ .name = base_name, .root_source_file = .{ .path = file_path } }); + build_step.install(); + + const verify_stepn = ZiglingStep.create(b, ex, use_healed); + if (i == 0) { + prev_step = &verify_stepn.step; + } else { + verify_stepn.step.dependOn(prev_step); + + prev_step = &verify_stepn.step; + } } + ziglings_step.dependOn(prev_step); } var use_color_escapes = false; @@ -627,10 +631,10 @@ var reset_text: []const u8 = ""; const ZiglingStep = struct { step: Step, exercise: Exercise, - builder: *Builder, + builder: *Build, use_healed: bool, - pub fn create(builder: *Builder, exercise: Exercise, use_healed: bool) *@This() { + pub fn create(builder: *Build, exercise: Exercise, use_healed: bool) *@This() { const self = builder.allocator.create(@This()) catch unreachable; self.* = .{ .step = Step.init(Step.Options{ .id = .custom, .name = exercise.main_file, .owner = builder, .makeFn = make }), @@ -650,7 +654,7 @@ const ZiglingStep = struct { } print("\n{s}Edit exercises/{s} and run this again.{s}", .{ red_text, self.exercise.main_file, reset_text }); - print("\n{s}To continue from this zigling, use this command:{s}\n {s}zig build {s}{s}\n", .{ red_text, reset_text, bold_text, self.exercise.key(), reset_text }); + print("\n{s}To continue from this zigling, use this command:{s}\n {s}zig build -Dn={s}{s}\n", .{ red_text, reset_text, bold_text, self.exercise.key(), reset_text }); std.os.exit(1); }; } @@ -804,3 +808,33 @@ const ZiglingStep = struct { }); } }; + +// Print a message to a file. +const PrintStep = struct { + step: Step, + message: []const u8, + file: std.fs.File, + + pub fn create(owner: *Build, message: []const u8, file: std.fs.File) *PrintStep { + const self = owner.allocator.create(PrintStep) catch @panic("OOM"); + self.* = .{ + .step = Step.init(.{ + .id = .custom, + .name = "Print", + .owner = owner, + .makeFn = make, + }), + .message = message, + .file = file, + }; + + return self; + } + + fn make(step: *Step, prog_node: *std.Progress.Node) !void { + _ = prog_node; + const p = @fieldParentPtr(PrintStep, "step", step); + + try p.file.writeAll(p.message); + } +}; |