Merge pull request 'Fix zig 0.15.0-dev.1149+4e6a04929 build errors' (#283) from zawupf/ziglings-exercises:zig-0.15 into main

Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/283
This commit is contained in:
Chris Boesch 2025-07-22 10:52:04 +02:00
commit 1f6ce9a268
9 changed files with 38 additions and 40 deletions

View File

@ -87,7 +87,8 @@ that if you update one, you may need to also update the other.
### Version Changes ### Version Changes
Version-0.14.0-dev.1573 Version-0.15.0-dev.1092
* *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488)
* *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257)
* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225)
* *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115)

View File

@ -15,7 +15,7 @@ const print = std.debug.print;
// 1) Getting Started // 1) Getting Started
// 2) Version Changes // 2) Version Changes
comptime { comptime {
const required_zig = "0.14.0-dev.1573"; const required_zig = "0.15.0-dev.1092";
const current_zig = builtin.zig_version; const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
if (current_zig.order(min_zig) == .lt) { if (current_zig.order(min_zig) == .lt) {
@ -126,19 +126,18 @@ pub fn build(b: *Build) !void {
if (!validate_exercises()) std.process.exit(2); if (!validate_exercises()) std.process.exit(2);
use_color_escapes = false; use_color_escapes = false;
if (std.io.getStdErr().supportsAnsiEscapeCodes()) { if (std.fs.File.stderr().supportsAnsiEscapeCodes()) {
use_color_escapes = true; use_color_escapes = true;
} else if (builtin.os.tag == .windows) { } else if (builtin.os.tag == .windows) {
const w32 = struct { const w32 = struct {
const WINAPI = std.os.windows.WINAPI;
const DWORD = std.os.windows.DWORD; const DWORD = std.os.windows.DWORD;
const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004; const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
const STD_ERROR_HANDLE: DWORD = @bitCast(@as(i32, -12)); const STD_ERROR_HANDLE: DWORD = @bitCast(@as(i32, -12));
extern "kernel32" fn GetStdHandle(id: DWORD) callconv(WINAPI) ?*anyopaque; const GetStdHandle = std.os.windows.kernel32.GetStdHandle;
extern "kernel32" fn GetConsoleMode(console: ?*anyopaque, out_mode: *DWORD) callconv(WINAPI) u32; const GetConsoleMode = std.os.windows.kernel32.GetConsoleMode;
extern "kernel32" fn SetConsoleMode(console: ?*anyopaque, mode: DWORD) callconv(WINAPI) u32; const SetConsoleMode = std.os.windows.kernel32.SetConsoleMode;
}; };
const handle = w32.GetStdHandle(w32.STD_ERROR_HANDLE); const handle = w32.GetStdHandle(w32.STD_ERROR_HANDLE).?;
var mode: w32.DWORD = 0; var mode: w32.DWORD = 0;
if (w32.GetConsoleMode(handle, &mode) != 0) { if (w32.GetConsoleMode(handle, &mode) != 0) {
mode |= w32.ENABLE_VIRTUAL_TERMINAL_PROCESSING; mode |= w32.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
@ -1064,7 +1063,7 @@ const exercises = [_]Exercise{
.{ .{
.main_file = "082_anonymous_structs3.zig", .main_file = "082_anonymous_structs3.zig",
.output = .output =
\\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.141592e0 \\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.141592
, ,
.hint = "This one is a challenge! But you have everything you need.", .hint = "This one is a challenge! But you have everything you need.",
}, },

View File

@ -16,12 +16,12 @@ const std = @import("std");
// //
pub fn main() !void { pub fn main() !void {
// We get a Writer for Standard Out so we can print() to it. // We get a Writer for Standard Out so we can print() to it.
const stdout = std.io.getStdOut().writer(); var stdout = std.fs.File.stdout().writer(&.{});
// Unlike std.debug.print(), the Standard Out writer can fail // Unlike std.debug.print(), the Standard Out writer can fail
// with an error. We don't care _what_ the error is, we want // with an error. We don't care _what_ the error is, we want
// to be able to pass it up as a return value of main(). // to be able to pass it up as a return value of main().
// //
// We just learned of a single statement which can accomplish this. // We just learned of a single statement which can accomplish this.
stdout.print("Hello world!\n", .{}); stdout.interface.print("Hello world!\n", .{});
} }

View File

@ -10,11 +10,11 @@ const std = @import("std");
const NumError = error{IllegalNumber}; const NumError = error{IllegalNumber};
pub fn main() void { pub fn main() void {
const stdout = std.io.getStdOut().writer(); var stdout = std.fs.File.stdout().writer(&.{});
const my_num: u32 = getNumber(); const my_num: u32 = getNumber();
try stdout.print("my_num={}\n", .{my_num}); try stdout.interface.print("my_num={}\n", .{my_num});
} }
// This function is obviously weird and non-functional. But you will not be changing it for this quiz. // This function is obviously weird and non-functional. But you will not be changing it for this quiz.

View File

@ -32,7 +32,7 @@ const print = std.debug.print;
pub fn main() !void { pub fn main() !void {
// let's check the pangram // let's check the pangram
print("Is this a pangram? {?}!\n", .{isPangram("The quick brown fox jumps over the lazy dog.")}); print("Is this a pangram? {}!\n", .{isPangram("The quick brown fox jumps over the lazy dog.")});
} }
fn isPangram(str: []const u8) bool { fn isPangram(str: []const u8) bool {
@ -45,7 +45,7 @@ fn isPangram(str: []const u8) bool {
// loop about all characters in the string // loop about all characters in the string
for (str) |c| { for (str) |c| {
// if the character is an alphabetical character // if the character is an alphabetical character
if (ascii.isASCII(c) and ascii.isAlphabetic(c)) { if (ascii.isAscii(c) and ascii.isAlphabetic(c)) {
// then we set the bit at the position // then we set the bit at the position
// //
// to do this, we use a little trick: // to do this, we use a little trick:

View File

@ -106,7 +106,7 @@ pub fn main() !void {
// After the threads have been started, // After the threads have been started,
// they run in parallel and we can still do some work in between. // they run in parallel and we can still do some work in between.
std.time.sleep(1500 * std.time.ns_per_ms); std.Thread.sleep(1500 * std.time.ns_per_ms);
std.debug.print("Some weird stuff, after starting the threads.\n", .{}); std.debug.print("Some weird stuff, after starting the threads.\n", .{});
} }
// After we have left the closed area, we wait until // After we have left the closed area, we wait until
@ -117,12 +117,12 @@ pub fn main() !void {
// This function is started with every thread that we set up. // This function is started with every thread that we set up.
// In our example, we pass the number of the thread as a parameter. // In our example, we pass the number of the thread as a parameter.
fn thread_function(num: usize) !void { fn thread_function(num: usize) !void {
std.time.sleep(200 * num * std.time.ns_per_ms); std.Thread.sleep(200 * num * std.time.ns_per_ms);
std.debug.print("thread {d}: {s}\n", .{ num, "started." }); std.debug.print("thread {d}: {s}\n", .{ num, "started." });
// This timer simulates the work of the thread. // This timer simulates the work of the thread.
const work_time = 3 * ((5 - num % 3) - 2); const work_time = 3 * ((5 - num % 3) - 2);
std.time.sleep(work_time * std.time.ns_per_s); std.Thread.sleep(work_time * std.time.ns_per_s);
std.debug.print("thread {d}: {s}\n", .{ num, "finished." }); std.debug.print("thread {d}: {s}\n", .{ num, "finished." });
} }

View File

@ -1,9 +1,9 @@
--- exercises/026_hello2.zig 2023-10-03 22:15:22.122241138 +0200 --- exercises/026_hello2.zig 2025-07-22 09:55:51.337832401 +0200
+++ answers/026_hello2.zig 2023-10-05 20:04:06.959431737 +0200 +++ answers/026_hello2.zig 2025-07-22 10:00:11.233348058 +0200
@@ -23,5 +23,5 @@ @@ -23,5 +23,5 @@
// to be able to pass it up as a return value of main(). // to be able to pass it up as a return value of main().
// //
// We just learned of a single statement which can accomplish this. // We just learned of a single statement which can accomplish this.
- stdout.print("Hello world!\n", .{}); - stdout.interface.print("Hello world!\n", .{});
+ try stdout.print("Hello world!\n", .{}); + try stdout.interface.print("Hello world!\n", .{});
} }

View File

@ -1,15 +1,15 @@
--- exercises/034_quiz4.zig 2023-10-03 22:15:22.122241138 +0200 --- exercises/034_quiz4.zig 2025-07-22 09:55:51.337832401 +0200
+++ answers/034_quiz4.zig 2023-10-05 20:04:06.996099091 +0200 +++ answers/034_quiz4.zig 2025-07-22 10:05:08.320323184 +0200
@@ -9,10 +9,10 @@ @@ -9,10 +9,10 @@
const NumError = error{IllegalNumber}; const NumError = error{IllegalNumber};
-pub fn main() void { -pub fn main() void {
+pub fn main() !void { +pub fn main() !void {
const stdout = std.io.getStdOut().writer(); var stdout = std.fs.File.stdout().writer(&.{});
- const my_num: u32 = getNumber(); - const my_num: u32 = getNumber();
+ const my_num: u32 = try getNumber(); + const my_num: u32 = try getNumber();
try stdout.print("my_num={}\n", .{my_num}); try stdout.interface.print("my_num={}\n", .{my_num});
} }

View File

@ -161,7 +161,7 @@ const CheckNamedStep = struct {
); );
defer stderr_file.close(); defer stderr_file.close();
const stderr = stderr_file.reader(); var stderr = stderr_file.readerStreaming(&.{});
{ {
// Skip the logo. // Skip the logo.
const nlines = mem.count(u8, root.logo, "\n"); const nlines = mem.count(u8, root.logo, "\n");
@ -169,10 +169,10 @@ const CheckNamedStep = struct {
var lineno: usize = 0; var lineno: usize = 0;
while (lineno < nlines) : (lineno += 1) { while (lineno < nlines) : (lineno += 1) {
_ = try readLine(stderr, &buf); _ = try readLine(&stderr, &buf);
} }
} }
try check_output(step, ex, stderr); try check_output(step, ex, &stderr);
} }
}; };
@ -213,7 +213,7 @@ const CheckStep = struct {
); );
defer stderr_file.close(); defer stderr_file.close();
const stderr = stderr_file.reader(); var stderr = stderr_file.readerStreaming(&.{});
for (exercises) |ex| { for (exercises) |ex| {
if (ex.number() == 1) { if (ex.number() == 1) {
// Skip the logo. // Skip the logo.
@ -222,15 +222,15 @@ const CheckStep = struct {
var lineno: usize = 0; var lineno: usize = 0;
while (lineno < nlines) : (lineno += 1) { while (lineno < nlines) : (lineno += 1) {
_ = try readLine(stderr, &buf); _ = try readLine(&stderr, &buf);
} }
} }
try check_output(step, ex, stderr); try check_output(step, ex, &stderr);
} }
} }
}; };
fn check_output(step: *Step, exercise: Exercise, reader: Reader) !void { fn check_output(step: *Step, exercise: Exercise, reader: *Reader) !void {
const b = step.owner; const b = step.owner;
var buf: [1024]u8 = undefined; var buf: [1024]u8 = undefined;
@ -297,12 +297,9 @@ fn check(
} }
} }
fn readLine(reader: fs.File.Reader, buf: []u8) !?[]const u8 { fn readLine(reader: *fs.File.Reader, buf: []u8) !?[]const u8 {
if (try reader.readUntilDelimiterOrEof(buf, '\n')) |line| { try reader.interface.readSliceAll(buf);
return mem.trimRight(u8, line, " \r\n"); return mem.trimRight(u8, buf, " \r\n");
}
return null;
} }
/// Fails with a custom error message. /// Fails with a custom error message.
@ -405,7 +402,8 @@ fn heal(allocator: Allocator, exercises: []const Exercise, work_path: []const u8
/// difference that returns an error when the temp path cannot be created. /// difference that returns an error when the temp path cannot be created.
pub fn makeTempPath(b: *Build) ![]const u8 { pub fn makeTempPath(b: *Build) ![]const u8 {
const rand_int = std.crypto.random.int(u64); const rand_int = std.crypto.random.int(u64);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ Build.hex64(rand_int); const rand_hex64 = std.fmt.hex(rand_int);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ rand_hex64;
const path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch const path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch
@panic("OOM"); @panic("OOM");
try b.cache_root.handle.makePath(tmp_dir_sub_path); try b.cache_root.handle.makePath(tmp_dir_sub_path);