build: restore support for Zig 0.6.0

The version check for Zig 0.6.0 was incorrect since commit
971ab7f (Use a zig build script to run ziglings).

Move compatibility support to a separate file, in order to simplify
build.zig.

In case of incompatible version, exit with code 3 instead of 0, in order
to detect the case of failure in a test (to be implemented).

Remove the use of comptime when checking compatibility at the start of
the build function, since it is not necessary.

Closes #210.
This commit is contained in:
Manlio Perillo 2023-04-03 11:06:39 +02:00
parent dd15cb94fd
commit 45713ec8ab
2 changed files with 75 additions and 48 deletions

View file

@ -1,15 +1,13 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const Builder = std.build.Builder; const compat = @import("src/compat.zig");
const Step = std.build.Step;
const Build = compat.Build;
const Step = compat.build.Step;
const assert = std.debug.assert; const assert = std.debug.assert;
const print = std.debug.print; 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 { const Exercise = struct {
/// main_file must have the format key_name.zig. /// main_file must have the format key_name.zig.
/// The key will be used as a shorthand to build /// The key will be used as a shorthand to build
@ -493,44 +491,8 @@ const exercises = [_]Exercise{
}, },
}; };
/// Check the zig version to make sure it can compile the examples properly. pub fn build(b: *Build) !void {
/// This will compile with Zig 0.6.0 and later. if (!compat.is_compatible) compat.die();
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);
}
use_color_escapes = false; use_color_escapes = false;
if (std.io.getStdErr().supportsAnsiEscapeCodes()) { if (std.io.getStdErr().supportsAnsiEscapeCodes()) {
@ -629,10 +591,10 @@ var reset_text: []const u8 = "";
const ZiglingStep = struct { const ZiglingStep = struct {
step: Step, step: Step,
exercise: Exercise, exercise: Exercise,
builder: *Builder, builder: *Build,
use_healed: bool, 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; const self = builder.allocator.create(@This()) catch unreachable;
self.* = .{ self.* = .{
.step = Step.init(Step.Options{ .id = .custom, .name = exercise.main_file, .owner = builder, .makeFn = make }), .step = Step.init(Step.Options{ .id = .custom, .name = exercise.main_file, .owner = builder, .makeFn = make }),
@ -813,7 +775,7 @@ const PrintStep = struct {
message: []const u8, message: []const u8,
file: std.fs.File, file: std.fs.File,
pub fn create(owner: *std.Build, message: []const u8, file: std.fs.File) *PrintStep { pub fn create(owner: *Build, message: []const u8, file: std.fs.File) *PrintStep {
const self = owner.allocator.create(PrintStep) catch @panic("OOM"); const self = owner.allocator.create(PrintStep) catch @panic("OOM");
self.* = .{ self.* = .{
.step = Step.init(.{ .step = Step.init(.{

65
src/compat.zig Normal file
View file

@ -0,0 +1,65 @@
/// Compatibility support for very old versions of Zig and recent versions before
/// commit efa25e7d5 (Merge pull request #14498 from ziglang/zig-build-api).
///
/// Versions of Zig from before 0.6.0 cannot do the version check and will just
/// fail to compile, but 0.5.0 was a long time ago, it is unlikely that anyone
/// who attempts these exercises is still using it.
const std = @import("std");
const builtin = @import("builtin");
const debug = std.debug;
// Very old versions of Zig used warn instead of print.
const print = if (@hasDecl(debug, "print")) debug.print else debug.warn;
// When changing this version, be sure to also update README.md in two places:
// 1) Getting Started
// 2) Version Changes
const needed_version_str = "0.11.0-dev.2157";
fn isCompatible() bool {
if (!@hasDecl(builtin, "zig_version") or !@hasDecl(std, "SemanticVersion")) {
return false;
}
const needed_version = std.SemanticVersion.parse(needed_version_str) catch unreachable;
const version = builtin.zig_version;
const order = version.order(needed_version);
return order != .lt;
}
pub fn die() noreturn {
const error_message =
\\ERROR: Sorry, it looks like your version of zig is too old. :-(
\\
\\Ziglings requires development build
\\
\\ {s}
\\
\\or higher. Please download a development ("master") build from
\\
\\ https://ziglang.org/download/
\\
\\
;
print(error_message, .{needed_version_str});
// Use exit code 2, to differentiate from a normal Zig compiler error.
std.os.exit(2);
}
// A separate function is required because very old versions of Zig doesn't
// support labeled block expressions.
pub const is_compatible: bool = isCompatible();
/// This is the type to be used only for the build function definition, since
/// the type must be compatible with the build runner.
///
/// Don't use std.Build.Builder, since it is deprecated and may be removed in
/// future.
pub const Build = if (is_compatible) std.Build else std.build.Builder;
/// This is the type to be used for accessing the build namespace.
pub const build = if (is_compatible) std.Build else std.build;