From 621100d3decfe11789f31179389a3a4cc68f0b68 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Sun, 29 Oct 2023 14:38:48 -0700 Subject: [PATCH] src/target: Restrict usable glibc versions At a minimum required glibc is v2.17, as earlier versions do not define some symbols (e.g., getauxval()) used by the Zig standard library. Additionally, glibc only supports some architectures at more recent versions (e.g., riscv64 support came in glibc v2.27). So add a `glibc_min` field to `available_libcs` for architectures with stronger version requirements. Extend the existing `canBuildLibC` function to check the target against the Zig minimum, and the architecture/os minimum. Also filter the list shown by `zig targets`, too: $ zig targets | jq -c '.glibc' ["2.17.0","2.18.0","2.19.0","2.20.0","2.21.0","2.22.0","2.23.0","2.24.0","2.25.0","2.26.0","2.27.0","2.28.0","2.29.0","2.30.0","2.31.0","2.32.0","2.33.0","2.34.0","2.35.0","2.36.0","2.37.0","2.38.0"] Fixes #17034 Fixes #17769 --- src/glibc.zig | 2 +- src/print_targets.zig | 9 ++++++--- src/target.zig | 25 ++++++++++++++++++++++--- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/glibc.zig b/src/glibc.zig index bdb5a080cbf3..720ea6170db6 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -20,7 +20,7 @@ pub const Lib = struct { }; pub const ABI = struct { - all_versions: []const Version, + all_versions: []const Version, // all defined versions (one abilist from v2.0.0 up to current) all_targets: []const target_util.ArchOsAbi, /// The bytes from the file verbatim, starting from the u16 number /// of function inclusions. diff --git a/src/print_targets.zig b/src/print_targets.zig index bfb2ac017702..f8390a03b921 100644 --- a/src/print_targets.zig +++ b/src/print_targets.zig @@ -79,9 +79,12 @@ pub fn cmdTargets( try jws.objectField("glibc"); try jws.beginArray(); for (glibc_abi.all_versions) |ver| { - const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver}); - defer allocator.free(tmp); - try jws.write(tmp); + // Actual glibc minimum is architecture specific. This just covers the broadest minimum. + if (ver.order(target.glibc_min_version) != .lt) { + const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver}); + defer allocator.free(tmp); + try jws.write(tmp); + } } try jws.endArray(); diff --git a/src/target.zig b/src/target.zig index cac9aa11b064..ce976884e056 100644 --- a/src/target.zig +++ b/src/target.zig @@ -8,10 +8,16 @@ pub const ArchOsAbi = struct { os: std.Target.Os.Tag, abi: std.Target.Abi, os_ver: ?std.SemanticVersion = null, + + // Minimum glibc version that provides support for the arch/os (for + // .abi = .gnu). For most entries, the .glibc_min is null, + // meaning the Zig minimum required by the standard library (see + // glibc_min_version) is sufficient. + glibc_min: ?std.SemanticVersion = null, }; pub const available_libcs = [_]ArchOsAbi{ - .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu }, + .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, .{ .arch = .aarch64_be, .os = .linux, .abi = .musl }, .{ .arch = .aarch64_be, .os = .windows, .abi = .gnu }, .{ .arch = .aarch64, .os = .linux, .abi = .gnu }, @@ -51,14 +57,14 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .mips, .os = .linux, .abi = .gnueabi }, .{ .arch = .mips, .os = .linux, .abi = .gnueabihf }, .{ .arch = .mips, .os = .linux, .abi = .musl }, - .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu }, + .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } }, .{ .arch = .powerpc64le, .os = .linux, .abi = .musl }, .{ .arch = .powerpc64, .os = .linux, .abi = .gnu }, .{ .arch = .powerpc64, .os = .linux, .abi = .musl }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf }, .{ .arch = .powerpc, .os = .linux, .abi = .musl }, - .{ .arch = .riscv64, .os = .linux, .abi = .gnu }, + .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } }, .{ .arch = .riscv64, .os = .linux, .abi = .musl }, .{ .arch = .s390x, .os = .linux, .abi = .gnu }, .{ .arch = .s390x, .os = .linux, .abi = .musl }, @@ -73,6 +79,9 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, }; +/// Minimum glibc version, due to dependencies from the Zig standard library on glibc symbols +pub const glibc_min_version: std.SemanticVersion = .{ .major = 2, .minor = 17, .patch = 0 }; + pub fn libCGenericName(target: std.Target) [:0]const u8 { switch (target.os.tag) { .windows => return "mingw", @@ -151,6 +160,16 @@ pub fn canBuildLibC(target: std.Target) bool { const ver = target.os.version_range.semver; return ver.min.order(libc.os_ver.?) != .lt; } + // Ensure target glibc version is supported + if (target.abi.isGnu()) { + if (target.os.tag != .linux) { // Zig only supports glibc on Linux + return false; + } + + const min_glibc_ver = libc.glibc_min orelse glibc_min_version; + const target_glibc_ver = target.os.version_range.linux.glibc; + return target_glibc_ver.order(min_glibc_ver) != .lt; + } return true; } }