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
This commit is contained in:
Pat Tullmann 2023-10-29 14:38:48 -07:00 committed by Andrew Kelley
parent 71e809852c
commit c22d1c00a8
3 changed files with 25 additions and 7 deletions

View file

@ -20,7 +20,7 @@ pub const Lib = struct {
}; };
pub const ABI = 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, all_targets: []const target_util.ArchOsAbi,
/// The bytes from the file verbatim, starting from the u16 number /// The bytes from the file verbatim, starting from the u16 number
/// of function inclusions. /// of function inclusions.

View file

@ -79,9 +79,12 @@ pub fn cmdTargets(
try jws.objectField("glibc"); try jws.objectField("glibc");
try jws.beginArray(); try jws.beginArray();
for (glibc_abi.all_versions) |ver| { for (glibc_abi.all_versions) |ver| {
const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver}); // Actual glibc minimum is architecture specific. This just covers the broadest minimum.
defer allocator.free(tmp); if (ver.order(target.glibc_min_version) != .lt) {
try jws.write(tmp); const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
defer allocator.free(tmp);
try jws.write(tmp);
}
} }
try jws.endArray(); try jws.endArray();

View file

@ -11,10 +11,16 @@ pub const ArchOsAbi = struct {
os: std.Target.Os.Tag, os: std.Target.Os.Tag,
abi: std.Target.Abi, abi: std.Target.Abi,
os_ver: ?std.SemanticVersion = null, 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{ 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 = .linux, .abi = .musl },
.{ .arch = .aarch64_be, .os = .windows, .abi = .gnu }, .{ .arch = .aarch64_be, .os = .windows, .abi = .gnu },
.{ .arch = .aarch64, .os = .linux, .abi = .gnu }, .{ .arch = .aarch64, .os = .linux, .abi = .gnu },
@ -54,14 +60,14 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .mips, .os = .linux, .abi = .gnueabi }, .{ .arch = .mips, .os = .linux, .abi = .gnueabi },
.{ .arch = .mips, .os = .linux, .abi = .gnueabihf }, .{ .arch = .mips, .os = .linux, .abi = .gnueabihf },
.{ .arch = .mips, .os = .linux, .abi = .musl }, .{ .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 = .powerpc64le, .os = .linux, .abi = .musl },
.{ .arch = .powerpc64, .os = .linux, .abi = .gnu }, .{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
.{ .arch = .powerpc64, .os = .linux, .abi = .musl }, .{ .arch = .powerpc64, .os = .linux, .abi = .musl },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
.{ .arch = .powerpc, .os = .linux, .abi = .musl }, .{ .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 = .riscv64, .os = .linux, .abi = .musl },
.{ .arch = .s390x, .os = .linux, .abi = .gnu }, .{ .arch = .s390x, .os = .linux, .abi = .gnu },
.{ .arch = .s390x, .os = .linux, .abi = .musl }, .{ .arch = .s390x, .os = .linux, .abi = .musl },
@ -76,6 +82,9 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, .{ .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 { pub fn libCGenericName(target: std.Target) [:0]const u8 {
switch (target.os.tag) { switch (target.os.tag) {
.windows => return "mingw", .windows => return "mingw",
@ -154,6 +163,12 @@ pub fn canBuildLibC(target: std.Target) bool {
const ver = target.os.version_range.semver; const ver = target.os.version_range.semver;
return ver.min.order(libc.os_ver.?) != .lt; return ver.min.order(libc.os_ver.?) != .lt;
} }
// Ensure glibc (aka *-linux-gnu) version is supported
if ((target.os.tag == .linux) and target.abi.isGnu()) {
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; return true;
} }
} }