authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-23 17:57:39+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-24 22:11:16+01:00
log24ecf45569f10743c5df6a39e6e71dcee265786a
treea2ed9bb83aa902511e10acc66d6d141b6d895e46
parent6d781e0955e7dd2b6cc17a5bb43c790e19a07ac0
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Target: Add Os.HurdVersionRange for Os.Tag.hurd.

This is necessary since isGnuLibC() is true for hurd, so we need to be able to represent a glibc version for it. Also add an Os.TaggedVersionRange.gnuLibCVersion() convenience function.

14 files changed, 111 insertions(+), 39 deletions(-)

lib/std/Build/Cache.zig+5
......@@ -217,6 +217,11 @@ pub const HashHelper = struct {
217217 },
218218 std.Target.Os.TaggedVersionRange => {
219219 switch (x) {
220 .hurd => |hurd| {
221 hh.add(hurd.range.min);
222 hh.add(hurd.range.max);
223 hh.add(hurd.glibc);
224 },
220225 .linux => |linux| {
221226 hh.add(linux.range.min);
222227 hh.add(linux.range.max);
lib/std/Target.zig+35-5
......@@ -187,7 +187,6 @@ pub const Os = struct {
187187 .hermit,
188188
189189 .aix,
190 .hurd,
191190 .rtems,
192191 .zos,
193192
......@@ -218,6 +217,7 @@ pub const Os = struct {
218217 .vulkan,
219218 => .semver,
220219
220 .hurd => .hurd,
221221 .linux => .linux,
222222
223223 .windows => .windows,
......@@ -356,6 +356,21 @@ pub const Os = struct {
356356 }
357357 };
358358
359 pub const HurdVersionRange = struct {
360 range: std.SemanticVersion.Range,
361 glibc: std.SemanticVersion,
362
363 pub inline fn includesVersion(range: HurdVersionRange, ver: std.SemanticVersion) bool {
364 return range.range.includesVersion(ver);
365 }
366
367 /// Checks if system is guaranteed to be at least `version` or older than `version`.
368 /// Returns `null` if a runtime check is required.
369 pub inline fn isAtLeast(range: HurdVersionRange, ver: std.SemanticVersion) ?bool {
370 return range.range.isAtLeast(ver);
371 }
372 };
373
359374 pub const LinuxVersionRange = struct {
360375 range: std.SemanticVersion.Range,
361376 glibc: std.SemanticVersion,
......@@ -400,6 +415,7 @@ pub const Os = struct {
400415 pub const VersionRange = union {
401416 none: void,
402417 semver: std.SemanticVersion.Range,
418 hurd: HurdVersionRange,
403419 linux: LinuxVersionRange,
404420 windows: WindowsVersion.Range,
405421
......@@ -456,9 +472,12 @@ pub const Os = struct {
456472 },
457473 },
458474 .hurd => .{
459 .semver = .{
460 .min = .{ .major = 0, .minor = 9, .patch = 0 },
461 .max = .{ .major = 0, .minor = 9, .patch = 0 },
475 .hurd = .{
476 .range = .{
477 .min = .{ .major = 0, .minor = 9, .patch = 0 },
478 .max = .{ .major = 0, .minor = 9, .patch = 0 },
479 },
480 .glibc = .{ .major = 2, .minor = 28, .patch = 0 },
462481 },
463482 },
464483 .linux => .{
......@@ -632,8 +651,17 @@ pub const Os = struct {
632651 pub const TaggedVersionRange = union(enum) {
633652 none: void,
634653 semver: std.SemanticVersion.Range,
654 hurd: HurdVersionRange,
635655 linux: LinuxVersionRange,
636656 windows: WindowsVersion.Range,
657
658 pub fn gnuLibCVersion(range: TaggedVersionRange) ?std.SemanticVersion {
659 return switch (range) {
660 .none, .semver, .windows => null,
661 .hurd => |h| h.glibc,
662 .linux => |l| l.glibc,
663 };
664 }
637665 };
638666
639667 /// Provides a tagged union. `Target` does not store the tag because it is
......@@ -642,6 +670,7 @@ pub const Os = struct {
642670 return switch (os.tag.versionRangeTag()) {
643671 .none => .{ .none = {} },
644672 .semver => .{ .semver = os.version_range.semver },
673 .hurd => .{ .hurd = os.version_range.hurd },
645674 .linux => .{ .linux = os.version_range.linux },
646675 .windows => .{ .windows = os.version_range.windows },
647676 };
......@@ -651,12 +680,13 @@ pub const Os = struct {
651680 /// Returns `null` if a runtime check is required.
652681 pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.versionRangeTag()) {
653682 .none => void,
654 .semver, .linux => std.SemanticVersion,
683 .semver, .hurd, .linux => std.SemanticVersion,
655684 .windows => WindowsVersion,
656685 }) ?bool {
657686 return if (os.tag != tag) false else switch (tag.versionRangeTag()) {
658687 .none => true,
659688 inline .semver,
689 .hurd,
660690 .linux,
661691 .windows,
662692 => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
lib/std/Target/Query.zig+5-5
......@@ -102,7 +102,7 @@ pub fn fromTarget(target: Target) Query {
102102 .os_version_min = undefined,
103103 .os_version_max = undefined,
104104 .abi = target.abi,
105 .glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null,
105 .glibc_version = target.os.versionRange().gnuLibCVersion(),
106106 .android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null,
107107 };
108108 result.updateOsVersionRange(target.os);
......@@ -132,9 +132,9 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void {
132132 .{ .semver = os.version_range.semver.min },
133133 .{ .semver = os.version_range.semver.max },
134134 },
135 .linux => .{
136 .{ .semver = os.version_range.linux.range.min },
137 .{ .semver = os.version_range.linux.range.max },
135 inline .hurd, .linux => |t| .{
136 .{ .semver = @field(os.version_range, @tagName(t)).range.min },
137 .{ .semver = @field(os.version_range, @tagName(t)).range.max },
138138 },
139139 .windows => .{
140140 .{ .windows = os.version_range.windows.min },
......@@ -544,7 +544,7 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
544544 const version_text = it.rest();
545545 if (version_text.len > 0) switch (tag.versionRangeTag()) {
546546 .none => return error.InvalidOperatingSystemVersion,
547 .semver, .linux => range: {
547 .semver, .hurd, .linux => range: {
548548 var range_it = mem.splitSequence(u8, version_text, "...");
549549 result.os_version_min = .{
550550 .semver = parseVersion(range_it.first()) catch |err| switch (err) {
lib/std/c.zig+2-3
......@@ -56,9 +56,8 @@ pub inline fn versionCheck(comptime version: std.SemanticVersion) bool {
5656 if (!builtin.link_libc) break :blk false;
5757 if (native_abi.isMusl()) break :blk true;
5858 if (builtin.target.isGnuLibC()) {
59 const ver = builtin.os.version_range.linux.glibc;
60 const order = ver.order(version);
61 break :blk switch (order) {
59 const ver = builtin.os.versionRange().gnuLibCVersion().?;
60 break :blk switch (ver.order(version)) {
6261 .gt, .eq => true,
6362 .lt => false,
6463 };
lib/std/zig/system.zig+8-5
......@@ -311,8 +311,8 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
311311
312312 if (query.os_version_min) |min| switch (min) {
313313 .none => {},
314 .semver => |semver| switch (os.tag) {
315 .linux => os.version_range.linux.range.min = semver,
314 .semver => |semver| switch (os.tag.versionRangeTag()) {
315 inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).range.min = semver,
316316 else => os.version_range.semver.min = semver,
317317 },
318318 .windows => |win_ver| os.version_range.windows.min = win_ver,
......@@ -320,15 +320,18 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
320320
321321 if (query.os_version_max) |max| switch (max) {
322322 .none => {},
323 .semver => |semver| switch (os.tag) {
324 .linux => os.version_range.linux.range.max = semver,
323 .semver => |semver| switch (os.tag.versionRangeTag()) {
324 inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).range.max = semver,
325325 else => os.version_range.semver.max = semver,
326326 },
327327 .windows => |win_ver| os.version_range.windows.max = win_ver,
328328 };
329329
330330 if (query.glibc_version) |glibc| {
331 os.version_range.linux.glibc = glibc;
331 switch (os.tag.versionRangeTag()) {
332 inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).glibc = glibc,
333 else => {},
334 }
332335 }
333336
334337 if (query.android_api_level) |android| {
lib/std/zig/target.zig+2-2
......@@ -88,10 +88,10 @@ pub fn canBuildLibC(target: std.Target) bool {
8888 const ver = target.os.version_range.semver;
8989 return ver.min.order(libc.os_ver.?) != .lt;
9090 }
91 // Ensure glibc (aka *-linux-gnu) version is supported
91 // Ensure glibc (aka *-(linux,hurd)-gnu) version is supported
9292 if (target.isGnuLibC()) {
9393 const min_glibc_ver = libc.glibc_min orelse return true;
94 const target_glibc_ver = target.os.version_range.linux.glibc;
94 const target_glibc_ver = target.os.versionRange().gnuLibCVersion().?;
9595 return target_glibc_ver.order(min_glibc_ver) != .lt;
9696 }
9797 return true;
src/Builtin.zig+34
......@@ -142,6 +142,40 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
142142
143143 linux.android,
144144 }),
145 .hurd => |hurd| try buffer.writer().print(
146 \\ .hurd = .{{
147 \\ .range = .{{
148 \\ .min = .{{
149 \\ .major = {},
150 \\ .minor = {},
151 \\ .patch = {},
152 \\ }},
153 \\ .max = .{{
154 \\ .major = {},
155 \\ .minor = {},
156 \\ .patch = {},
157 \\ }},
158 \\ }},
159 \\ .glibc = .{{
160 \\ .major = {},
161 \\ .minor = {},
162 \\ .patch = {},
163 \\ }},
164 \\ }}}},
165 \\
166 , .{
167 hurd.range.min.major,
168 hurd.range.min.minor,
169 hurd.range.min.patch,
170
171 hurd.range.max.major,
172 hurd.range.max.minor,
173 hurd.range.max.patch,
174
175 hurd.glibc.major,
176 hurd.glibc.minor,
177 hurd.glibc.patch,
178 }),
145179 .windows => |windows| try buffer.writer().print(
146180 \\ .windows = .{{
147181 \\ .min = {c},
src/Compilation.zig+1-1
......@@ -5315,7 +5315,7 @@ pub fn addCCArgs(
53155315
53165316 if (comp.config.link_libc) {
53175317 if (target.isGnuLibC()) {
5318 const target_version = target.os.version_range.linux.glibc;
5318 const target_version = target.os.versionRange().gnuLibCVersion().?;
53195319 const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
53205320 target_version.minor,
53215321 });
src/codegen/llvm.zig+10-6
......@@ -245,7 +245,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
245245 ver.min.minor,
246246 ver.min.patch,
247247 }),
248 .linux => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
248 inline .linux, .hurd => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
249249 ver.range.min.major,
250250 ver.range.min.minor,
251251 ver.range.min.patch,
......@@ -290,11 +290,15 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
290290 .semver,
291291 .windows,
292292 => {},
293 .linux => |ver| if (target.abi.isGnu()) try llvm_triple.writer().print("{d}.{d}.{d}", .{
294 ver.glibc.major,
295 ver.glibc.minor,
296 ver.glibc.patch,
297 }) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}),
293 inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
294 try llvm_triple.writer().print("{d}.{d}.{d}", .{
295 ver.glibc.major,
296 ver.glibc.minor,
297 ver.glibc.patch,
298 });
299 } else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
300 try llvm_triple.writer().print("{d}", .{ver.android});
301 },
298302 }
299303
300304 return llvm_triple.toOwnedSlice();
src/glibc.zig+3-3
......@@ -188,7 +188,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
188188 const arena = arena_allocator.allocator();
189189
190190 const target = comp.root_mod.resolved_target.result;
191 const target_ver = target.os.version_range.linux.glibc;
191 const target_ver = target.os.versionRange().gnuLibCVersion().?;
192192 const nonshared_stat = target_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) != .gt;
193193 const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt;
194194
......@@ -750,7 +750,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
750750 const arena = arena_allocator.allocator();
751751
752752 const target = comp.getTarget();
753 const target_version = target.os.version_range.linux.glibc;
753 const target_version = target.os.versionRange().gnuLibCVersion().?;
754754
755755 // Use the global cache directory.
756756 var cache: Cache = .{
......@@ -1218,7 +1218,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
12181218}
12191219
12201220fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1221 const target_version = comp.getTarget().os.version_range.linux.glibc;
1221 const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;
12221222
12231223 assert(comp.glibc_so_files == null);
12241224 comp.glibc_so_files = so_files;
src/libcxx.zig+3-3
......@@ -262,7 +262,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
262262
263263 if (target.isGnuLibC()) {
264264 // glibc 2.16 introduced aligned_alloc
265 if (target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
265 if (target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
266266 try cflags.append("-D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION");
267267 }
268268 }
......@@ -477,7 +477,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
477477 }
478478 try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
479479 } else if (target.abi.isGnu()) {
480 if (target.os.tag != .linux or !(target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 18, .patch = 0 }) == .lt))
480 if (target.os.tag != .linux or !(target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 18, .patch = 0 }) == .lt))
481481 try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
482482 }
483483
......@@ -500,7 +500,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
500500
501501 if (target.isGnuLibC()) {
502502 // glibc 2.16 introduced aligned_alloc
503 if (target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
503 if (target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
504504 try cflags.append("-D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION");
505505 }
506506 }
src/link/Elf.zig+1-1
......@@ -2013,7 +2013,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
20132013 } else if (target.isGnuLibC()) {
20142014 for (glibc.libs) |lib| {
20152015 if (lib.removed_in) |rem_in| {
2016 if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue;
2016 if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
20172017 }
20182018
20192019 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
test/link/glibc_compat/build.zig+1-4
......@@ -5,10 +5,7 @@ const builtin = @import("builtin");
55// run-time glibc version needs to be new enough. Check the host's glibc
66// version. Note that this does not allow for translation/vm/emulation
77// services to run these tests.
8const running_glibc_ver: ?std.SemanticVersion = switch (builtin.os.tag) {
9 .linux => builtin.os.version_range.linux.glibc,
10 else => null,
11};
8const running_glibc_ver = builtin.os.versionRange().gnuLibCVersion();
129
1310pub fn build(b: *std.Build) void {
1411 const test_step = b.step("test", "Test");
test/link/glibc_compat/glibc_runtime_check.zig+1-1
......@@ -21,7 +21,7 @@ const c_string = @cImport(
2121);
2222
2323// Version of glibc this test is being built to run against
24const glibc_ver = builtin.target.os.version_range.linux.glibc;
24const glibc_ver = builtin.os.versionRange().gnuLibCVersion().?;
2525
2626// PR #17034 - fstat moved between libc_nonshared and libc
2727fn checkStat() !void {