Skip to content

Commit

Permalink
build_runner: handle non semver ĺinux kernel release versions
Browse files Browse the repository at this point in the history
  • Loading branch information
Techatrix committed Jan 26, 2025
1 parent ab187cc commit 16cf11b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
7 changes: 3 additions & 4 deletions src/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ const Workspace = struct {
}) error{OutOfMemory}!void {
comptime std.debug.assert(BuildOnSave.isSupportedComptime());

const build_on_save_supported = if (args.runtime_zig_version) |version| BuildOnSave.isSupportedRuntime(version) else false;
const build_on_save_supported = if (args.runtime_zig_version) |version| BuildOnSave.isSupportedRuntime(version, false) else false;
const build_on_save_wanted = args.server.config.enable_build_on_save orelse true;
const enable = build_on_save_supported and build_on_save_wanted;

Expand Down Expand Up @@ -1075,9 +1075,8 @@ pub fn updateConfiguration(
log.warn("'enable_build_on_save' is ignored because it is not supported by {s}", .{server.client_capabilities.client_name orelse "your editor"});
} else if (server.status == .initialized and options.resolve and resolve_result.build_runner_version == .unresolved and server.config.build_runner_path == null) {
log.warn("'enable_build_on_save' is ignored because no build runner is available", .{});
} else if (server.status == .initialized and options.resolve and resolve_result.zig_runtime_version != null and !BuildOnSave.isSupportedRuntime(resolve_result.zig_runtime_version.?)) {
// There is one edge-case where build on save is not supported because of Linux pre 5.17
log.warn("'enable_build_on_save' is not supported by Zig {}", .{resolve_result.zig_runtime_version.?});
} else if (server.status == .initialized and options.resolve and resolve_result.zig_runtime_version != null and !BuildOnSave.isSupportedRuntime(resolve_result.zig_runtime_version.?, true)) {
// already logged
}
}

Expand Down
41 changes: 37 additions & 4 deletions src/features/diagnostics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -548,21 +548,25 @@ pub const BuildOnSave = struct {
return true;
}

pub fn isSupportedRuntime(runtime_zig_version: std.SemanticVersion) bool {
if (!isSupportedComptime()) return false;
pub fn isSupportedRuntime(runtime_zig_version: std.SemanticVersion, log_message: bool) bool {
comptime std.debug.assert(isSupportedComptime());

if (builtin.os.tag == .linux) blk: {
// std.build.Watch requires `FAN_REPORT_TARGET_FID` which is Linux 5.17+
const utsname = std.posix.uname();
const version = std.SemanticVersion.parse(&utsname.release) catch break :blk;
const version = parseUnameKernelVersion(&utsname.release) catch |err| {
if (log_message) log.warn("failed to parse kernel version '{s}': {}", .{ utsname.release, err });
break :blk;
};
if (version.order(.{ .major = 5, .minor = 17, .patch = 0 }) != .lt) break :blk;
if (log_message) log.err("Build-On-Save is not supported by Linux '{s}' (requires 5.17+)", .{utsname.release});
return false;
}

// We can't rely on `std.Build.Watch.have_impl` because we need to
// check the runtime Zig version instead of Zig version that ZLS
// has been built with.
return switch (builtin.os.tag) {
const zig_version_supported = switch (builtin.os.tag) {
.linux => true,
.windows => runtime_zig_version.order(windows_support_version) != .lt,
.dragonfly,
Expand All @@ -578,6 +582,35 @@ pub const BuildOnSave = struct {
=> runtime_zig_version.order(kqueue_support_version) != .lt,
else => false,
};

if (!zig_version_supported) {
log.warn("Build-On-Save is not supported on {s} by Zig {}", .{ @tagName(builtin.os.tag), runtime_zig_version });
}

return zig_version_supported;
}

fn parseUnameKernelVersion(kernel_version: []const u8) !std.SemanticVersion {
const extra_index = std.mem.indexOfAny(u8, kernel_version, "-+");
const required = kernel_version[0..(extra_index orelse kernel_version.len)];
var it = std.mem.splitScalar(u8, required, '.');
return .{
.major = try std.fmt.parseUnsigned(usize, it.next() orelse return error.InvalidVersion, 10),
.minor = try std.fmt.parseUnsigned(usize, it.next() orelse return error.InvalidVersion, 10),
.patch = try std.fmt.parseUnsigned(usize, it.next() orelse return error.InvalidVersion, 10),
};
}

test parseUnameKernelVersion {
try std.testing.expectFmt("5.17.0", "{}", .{try parseUnameKernelVersion("5.17.0")});
try std.testing.expectFmt("6.12.9", "{}", .{try parseUnameKernelVersion("6.12.9-rc7")});
try std.testing.expectFmt("6.6.71", "{}", .{try parseUnameKernelVersion("6.6.71-42-generic")});
try std.testing.expectFmt("5.15.167", "{}", .{try parseUnameKernelVersion("5.15.167.4-microsoft-standard-WSL2")}); // WSL2
try std.testing.expectFmt("4.4.0", "{}", .{try parseUnameKernelVersion("4.4.0-20241-Microsoft")}); // WSL1

try std.testing.expectError(error.InvalidCharacter, parseUnameKernelVersion(""));
try std.testing.expectError(error.InvalidVersion, parseUnameKernelVersion("5"));
try std.testing.expectError(error.InvalidVersion, parseUnameKernelVersion("5.5"));
}

fn loop(
Expand Down

0 comments on commit 16cf11b

Please sign in to comment.