Skip to content

Commit ea02397

Browse files
committed
Zig 0.16 Compatibility
This makes libxev work with Zig 0.16. **Fair warning that this is messy.** The goal was to keep libxev working with minimal external API changes. That means we don't play nicely with `std.Io` yet and I'm not 100% sure what the path forward is for that since in many ways libxev is an alternate implementation but std.Io doesn't have full coverage for our functionality so we can't simply switch to it either. In cases wher we need an Io here, I use the global single threaded Io which preserves the Zig 0.15 behavior. Like I said, the goal is to get people who use libxev (including me) upgraded to 0.16, not to fully adapt to the new idioms. Particularly nasty is the large amount of shims we need in `src/posix.zig` and `src/windows.zig` to address removed APIs from Zig.
1 parent d398cba commit ea02397

37 files changed

Lines changed: 2218 additions & 718 deletions

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
on: [push, pull_request]
22
name: Test
33
env:
4-
ZIG_VERSION: 0.15.2
4+
ZIG_VERSION: 0.16.0
55

66
jobs:
77
build:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ directory.
272272

273273
# Build
274274

275-
Build requires the installation of the Zig 0.15.1. libxev follows stable
275+
Build requires the installation of the Zig 0.16. libxev follows stable
276276
Zig releases and generally does not support nightly builds. When a stable
277277
release is imminent we may have a branch that supports it.
278278
**libxev has no other build dependencies.**

build.zig

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub fn build(b: *std.Build) !void {
2626
true
2727
else |err| switch (err) {
2828
error.FileNotFound => false,
29-
else => return err,
3029
};
3130

3231
const emit_bench = b.option(
@@ -41,25 +40,23 @@ pub fn build(b: *std.Build) !void {
4140
"Install the example binaries to zig-out",
4241
) orelse false;
4342

44-
const c_api_module = b.createModule(.{
45-
.root_source_file = b.path("src/c_api.zig"),
46-
.target = target,
47-
.optimize = optimize,
48-
});
49-
5043
// Static C lib
5144
const static_lib: ?*Step.Compile = lib: {
5245
if (target.result.os.tag == .wasi) break :lib null;
5346

5447
const static_lib = b.addLibrary(.{
5548
.linkage = .static,
5649
.name = "xev",
57-
.root_module = c_api_module,
50+
.root_module = b.createModule(.{
51+
.root_source_file = b.path("src/c_api.zig"),
52+
.target = target,
53+
.optimize = optimize,
54+
.link_libc = true,
55+
}),
5856
});
59-
static_lib.linkLibC();
6057
if (target.result.os.tag == .windows) {
61-
static_lib.linkSystemLibrary("ws2_32");
62-
static_lib.linkSystemLibrary("mswsock");
58+
static_lib.root_module.linkSystemLibrary("ws2_32", .{});
59+
static_lib.root_module.linkSystemLibrary("mswsock", .{});
6360
}
6461
break :lib static_lib;
6562
};
@@ -72,7 +69,11 @@ pub fn build(b: *std.Build) !void {
7269
const dynamic_lib = b.addLibrary(.{
7370
.linkage = .dynamic,
7471
.name = "xev",
75-
.root_module = c_api_module,
72+
.root_module = b.createModule(.{
73+
.root_source_file = b.path("src/c_api.zig"),
74+
.target = target,
75+
.optimize = optimize,
76+
}),
7677
});
7778
break :lib dynamic_lib;
7879
};
@@ -119,20 +120,19 @@ pub fn build(b: *std.Build) !void {
119120
"test-filter",
120121
"Filter for test",
121122
);
122-
const test_exe = b.addTest(.{
123+
break :test_exe b.addTest(.{
123124
.name = "xev-test",
124125
.filters = if (test_filter) |filter| &.{filter} else &.{},
125126
.root_module = b.createModule(.{
126127
.root_source_file = b.path("src/main.zig"),
127128
.target = target,
128129
.optimize = optimize,
130+
.link_libc = switch (target.result.os.tag) {
131+
.linux, .macos => true,
132+
else => null,
133+
},
129134
}),
130135
});
131-
switch (target.result.os.tag) {
132-
.linux, .macos => test_exe.linkLibC(),
133-
else => {},
134-
}
135-
break :test_exe test_exe;
136136
};
137137

138138
// "test" Step
@@ -172,19 +172,24 @@ fn buildBenchmarks(
172172
b: *std.Build,
173173
target: std.Build.ResolvedTarget,
174174
) ![]const *Step.Compile {
175+
const io = b.graph.io;
175176
const alloc = b.allocator;
176177
var steps: std.ArrayList(*Step.Compile) = .empty;
177178
defer steps.deinit(alloc);
178179

179-
var dir = try std.fs.cwd().openDir(try b.build_root.join(
180-
b.allocator,
181-
&.{ "src", "bench" },
182-
), .{ .iterate = true });
183-
defer dir.close();
180+
var dir = try std.Io.Dir.cwd().openDir(
181+
io,
182+
try b.build_root.join(
183+
b.allocator,
184+
&.{ "src", "bench" },
185+
),
186+
.{ .iterate = true },
187+
);
188+
defer dir.close(io);
184189

185190
// Go through and add each as a step
186191
var it = dir.iterate();
187-
while (try it.next()) |entry| {
192+
while (try it.next(io)) |entry| {
188193
// Get the index of the last '.' so we can strip the extension.
189194
const index = std.mem.lastIndexOfScalar(
190195
u8,
@@ -223,19 +228,24 @@ fn buildExamples(
223228
optimize: std.builtin.OptimizeMode,
224229
c_lib_: ?*Step.Compile,
225230
) ![]const *Step.Compile {
231+
const io = b.graph.io;
226232
const alloc = b.allocator;
227233
var steps: std.ArrayList(*Step.Compile) = .empty;
228234
defer steps.deinit(alloc);
229235

230-
var dir = try std.fs.cwd().openDir(try b.build_root.join(
231-
b.allocator,
232-
&.{"examples"},
233-
), .{ .iterate = true });
234-
defer dir.close();
236+
var dir = try std.Io.Dir.cwd().openDir(
237+
io,
238+
try b.build_root.join(
239+
b.allocator,
240+
&.{"examples"},
241+
),
242+
.{ .iterate = true },
243+
);
244+
defer dir.close(io);
235245

236246
// Go through and add each as a step
237247
var it = dir.iterate();
238-
while (try it.next()) |entry| {
248+
while (try it.next(io)) |entry| {
239249
// Get the index of the last '.' so we can strip the extension.
240250
const index = std.mem.lastIndexOfScalar(
241251
u8,
@@ -269,11 +279,11 @@ fn buildExamples(
269279
.root_module = b.createModule(.{
270280
.target = target,
271281
.optimize = optimize,
282+
.link_libc = true,
272283
}),
273284
});
274-
exe.linkLibC();
275-
exe.addIncludePath(b.path("include"));
276-
exe.addCSourceFile(.{
285+
exe.root_module.addIncludePath(b.path("include"));
286+
exe.root_module.addCSourceFile(.{
277287
.file = b.path(b.fmt(
278288
"examples/{s}",
279289
.{entry.name},
@@ -286,7 +296,7 @@ fn buildExamples(
286296
"-D_POSIX_C_SOURCE=199309L",
287297
},
288298
});
289-
exe.linkLibrary(c_lib);
299+
exe.root_module.linkLibrary(c_lib);
290300
break :exe exe;
291301
};
292302

@@ -298,18 +308,20 @@ fn buildExamples(
298308
}
299309

300310
fn manPages(b: *std.Build) ![]const *Step {
311+
const io = b.graph.io;
301312
const alloc = b.allocator;
302313
var steps: std.ArrayList(*Step) = .empty;
303314
defer steps.deinit(alloc);
304315

305-
var dir = try std.fs.cwd().openDir(try b.build_root.join(
306-
b.allocator,
307-
&.{"docs"},
308-
), .{ .iterate = true });
309-
defer dir.close();
316+
var dir = try std.Io.Dir.cwd().openDir(
317+
io,
318+
try b.build_root.join(b.allocator, &.{"docs"}),
319+
.{ .iterate = true },
320+
);
321+
defer dir.close(io);
310322

311323
var it = dir.iterate();
312-
while (try it.next()) |*entry| {
324+
while (try it.next(io)) |*entry| {
313325
// Filenames must end in "{section}.scd" and sections are
314326
// single numerals.
315327
const base = entry.name[0 .. entry.name.len - 4];
@@ -321,7 +333,7 @@ fn manPages(b: *std.Build) ![]const *Step {
321333
) });
322334

323335
try steps.append(alloc, &b.addInstallFile(
324-
cmd.captureStdOut(),
336+
cmd.captureStdOut(.{}),
325337
b.fmt("share/man/man{s}/{s}", .{ section, base }),
326338
).step);
327339
}

build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .libxev,
3-
.minimum_zig_version = "0.15.1",
3+
.minimum_zig_version = "0.16.0",
44
.version = "0.0.0",
55
.fingerprint = 0x30f7363573edabf3,
66
.paths = .{""},

examples/_basic.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const std = @import("std");
2-
const Instant = std.time.Instant;
32
const xev = @import("xev");
43

54
pub fn main() !void {

flake.lock

Lines changed: 10 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# Other overlays
2424
(final: prev: rec {
2525
zigpkgs = inputs.zig.packages.${prev.system};
26-
zig = inputs.zig.packages.${prev.system}."0.15.2";
26+
zig = inputs.zig.packages.${prev.system}."0.16.0";
2727

2828
# Our package
2929
libxev = prev.callPackage ./nix/package.nix {};

src/ThreadPool.zig

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ const ThreadPool = @This();
3939
const std = @import("std");
4040
const assert = std.debug.assert;
4141
const Atomic = std.atomic.Value;
42+
const Io = std.Io;
43+
44+
// I know we shouldn't use a global io here, but we are doing this
45+
// during the transition period so libxev is at least usable with Zig
46+
// 0.16 until we do a cleaner transition.
47+
const io = Io.Threaded.global_single_threaded.io();
4248

4349
stack_size: u32,
4450
max_threads: u32,
@@ -487,7 +493,7 @@ const Event = struct {
487493
// Acquiring to WAITING will make the next notify() or shutdown() wake a sleeping futex thread
488494
// who will either exit on SHUTDOWN or acquire with WAITING again, ensuring all threads are awoken.
489495
// This unfortunately results in the last notify() or shutdown() doing an extra futex wake but that's fine.
490-
std.Thread.Futex.wait(&self.state, WAITING);
496+
io.futexWaitUncancelable(u32, &self.state.raw, WAITING);
491497
state = self.state.load(.monotonic);
492498
acquire_with = WAITING;
493499
}
@@ -513,7 +519,7 @@ const Event = struct {
513519
// Only wake threads sleeping in futex if the state is WAITING.
514520
// Avoids unnecessary wake ups.
515521
if (state == WAITING) {
516-
std.Thread.Futex.wake(&self.state, wake_threads);
522+
io.futexWake(u32, &self.state.raw, wake_threads);
517523
}
518524
}
519525
};

src/api.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ pub fn Xev(comptime be: Backend, comptime T: type) type {
6565
pub const TCP = @import("watcher/tcp.zig").TCP(Self);
6666
pub const UDP = @import("watcher/udp.zig").UDP(Self);
6767

68+
/// Networking types shared across watchers.
69+
pub const net = @import("posix.zig").net;
70+
6871
/// The callback of the main Loop operations. Higher level interfaces may
6972
/// use a different callback mechanism.
7073
pub const Callback = loop.Callback(T);

0 commit comments

Comments
 (0)