Skip to content

Commit

Permalink
Merge pull request #22090 from alexrp/glibc-runtime-triples
Browse files Browse the repository at this point in the history
Add `std.zig.target.glibcRuntimeTriple()` and use it in `std.Build.Step.Run` and `process_headers.zig`
  • Loading branch information
alexrp authored Dec 12, 2024
2 parents 3f7b3da + 9293e04 commit d48611b
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 90 deletions.
32 changes: 13 additions & 19 deletions lib/std/Build/Step/Run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,8 @@ fn runCommand(
else => break :interpret,
}

const need_cross_glibc = exe.rootModuleTarget().isGnuLibC() and
const root_target = exe.rootModuleTarget();
const need_cross_glibc = root_target.isGnuLibC() and
exe.is_linking_libc;
const other_target = exe.root_module.resolved_target.?.result;
switch (std.zig.system.getExternalExecutor(b.graph.host.result, &other_target, .{
Expand Down Expand Up @@ -1039,23 +1040,16 @@ fn runCommand(
try interp_argv.append(bin_name);

if (glibc_dir_arg) |dir| {
// TODO look into making this a call to `linuxTriple`. This
// needs the directory to be called "i686" rather than
// "x86" which is why we do it manually here.
const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";
const cpu_arch = exe.rootModuleTarget().cpu.arch;
const os_tag = exe.rootModuleTarget().os.tag;
const abi = exe.rootModuleTarget().abi;
const cpu_arch_name: []const u8 = if (cpu_arch == .x86)
"i686"
else
@tagName(cpu_arch);
const full_dir = try std.fmt.allocPrint(b.allocator, fmt_str, .{
dir, cpu_arch_name, @tagName(os_tag), @tagName(abi),
});

try interp_argv.append("-L");
try interp_argv.append(full_dir);
try interp_argv.append(b.pathJoin(&.{
dir,
try std.zig.target.glibcRuntimeTriple(
b.allocator,
root_target.cpu.arch,
root_target.os.tag,
root_target.abi,
),
}));
}

try interp_argv.appendSlice(argv);
Expand Down Expand Up @@ -1113,15 +1107,15 @@ fn runCommand(
if (allow_skip) return error.MakeSkipped;

const host_name = try b.graph.host.result.zigTriple(b.allocator);
const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator);
const foreign_name = try root_target.zigTriple(b.allocator);

return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{
host_name, foreign_name,
});
},
}

if (exe.rootModuleTarget().os.tag == .windows) {
if (root_target.os.tag == .windows) {
// On Windows we don't have rpaths so we have to add .dll search paths to PATH
run.addPathForDynLibs(exe);
}
Expand Down
8 changes: 8 additions & 0 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2013,6 +2013,14 @@ pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
return Query.fromTarget(target).zigTriple(allocator);
}

pub fn hurdTupleSimple(allocator: Allocator, arch: Cpu.Arch, abi: Abi) ![]u8 {
return std.fmt.allocPrint(allocator, "{s}-{s}", .{ @tagName(arch), @tagName(abi) });
}

pub fn hurdTuple(target: Target, allocator: Allocator) ![]u8 {
return hurdTupleSimple(allocator, target.cpu.arch, target.abi);
}

pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
}
Expand Down
67 changes: 48 additions & 19 deletions lib/std/zig/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ pub const ArchOsAbi = struct {
abi: std.Target.Abi,
os_ver: ?std.SemanticVersion = null,

// Minimum glibc version that provides support for the arch/os when ABI is GNU.
/// Minimum glibc version that provides support for the arch/os when ABI is GNU.
glibc_min: ?std.SemanticVersion = null,
/// Override for `glibcRuntimeTriple` when glibc has an unusual directory name for the target.
glibc_triple: ?[]const u8 = null,
};

pub const available_libcs = [_]ArchOsAbi{
Expand All @@ -29,52 +31,52 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .aarch64, .os = .windows, .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 = .csky, .os = .linux, .abi = .gnueabi, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 } },
.{ .arch = .csky, .os = .linux, .abi = .gnueabihf, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 } },
.{ .arch = .loongarch64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 } },
.{ .arch = .loongarch64, .os = .linux, .abi = .gnusf, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 } },
.{ .arch = .csky, .os = .linux, .abi = .gnueabi, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 }, .glibc_triple = "csky-linux-gnuabiv2-soft" },
.{ .arch = .csky, .os = .linux, .abi = .gnueabihf, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 }, .glibc_triple = "csky-linux-gnuabiv2" },
.{ .arch = .loongarch64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 }, .glibc_triple = "loongarch64-linux-gnu-lp64d" },
.{ .arch = .loongarch64, .os = .linux, .abi = .gnusf, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 }, .glibc_triple = "loongarch64-linux-gnu-lp64s" },
.{ .arch = .loongarch64, .os = .linux, .abi = .musl },
.{ .arch = .m68k, .os = .linux, .abi = .gnu },
.{ .arch = .m68k, .os = .linux, .abi = .musl },
.{ .arch = .mips, .os = .linux, .abi = .gnueabi },
.{ .arch = .mips, .os = .linux, .abi = .gnueabihf },
.{ .arch = .mips, .os = .linux, .abi = .gnueabi, .glibc_triple = "mips-linux-gnu-soft" },
.{ .arch = .mips, .os = .linux, .abi = .gnueabihf, .glibc_triple = "mips-linux-gnu" },
.{ .arch = .mips, .os = .linux, .abi = .musleabi },
.{ .arch = .mips, .os = .linux, .abi = .musleabihf },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabi },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabihf },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabi, .glibc_triple = "mipsel-linux-gnu-soft" },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabihf, .glibc_triple = "mipsel-linux-gnu" },
.{ .arch = .mipsel, .os = .linux, .abi = .musleabi },
.{ .arch = .mipsel, .os = .linux, .abi = .musleabihf },
.{ .arch = .mips64, .os = .linux, .abi = .gnuabi64 },
.{ .arch = .mips64, .os = .linux, .abi = .gnuabin32 },
.{ .arch = .mips64, .os = .linux, .abi = .gnuabi64, .glibc_triple = "mips64-linux-gnu-n64" },
.{ .arch = .mips64, .os = .linux, .abi = .gnuabin32, .glibc_triple = "mips64-linux-gnu-n32" },
.{ .arch = .mips64, .os = .linux, .abi = .muslabi64 },
.{ .arch = .mips64, .os = .linux, .abi = .muslabin32 },
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabi64 },
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabin32 },
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabi64, .glibc_triple = "mips64el-linux-gnu-n64" },
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabin32, .glibc_triple = "mips64el-linux-gnu-n32" },
.{ .arch = .mips64el, .os = .linux, .abi = .muslabi64 },
.{ .arch = .mips64el, .os = .linux, .abi = .muslabin32 },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi, .glibc_triple = "powerpc-linux-gnu-soft" },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf, .glibc_triple = "powerpc-linux-gnu" },
.{ .arch = .powerpc, .os = .linux, .abi = .musleabi },
.{ .arch = .powerpc, .os = .linux, .abi = .musleabihf },
.{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
.{ .arch = .powerpc64, .os = .linux, .abi = .musl },
.{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } },
.{ .arch = .powerpc64le, .os = .linux, .abi = .musl },
.{ .arch = .riscv32, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
.{ .arch = .riscv32, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 }, .glibc_triple = "riscv32-linux-gnu-rv32imafdc-ilp32d" },
.{ .arch = .riscv32, .os = .linux, .abi = .musl },
.{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
.{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 }, .glibc_triple = "riscv64-linux-gnu-rv64imafdc-lp64d" },
.{ .arch = .riscv64, .os = .linux, .abi = .musl },
.{ .arch = .s390x, .os = .linux, .abi = .gnu },
.{ .arch = .s390x, .os = .linux, .abi = .musl },
.{ .arch = .sparc, .os = .linux, .abi = .gnu },
.{ .arch = .sparc, .os = .linux, .abi = .gnu, .glibc_triple = "sparcv9-linux-gnu" },
.{ .arch = .sparc64, .os = .linux, .abi = .gnu },
.{ .arch = .wasm32, .os = .freestanding, .abi = .musl },
.{ .arch = .wasm32, .os = .wasi, .abi = .musl },
.{ .arch = .x86, .os = .linux, .abi = .gnu },
.{ .arch = .x86, .os = .linux, .abi = .musl },
.{ .arch = .x86, .os = .windows, .abi = .gnu },
.{ .arch = .x86_64, .os = .linux, .abi = .gnu },
.{ .arch = .x86_64, .os = .linux, .abi = .gnux32 },
.{ .arch = .x86_64, .os = .linux, .abi = .gnux32, .glibc_triple = "x86_64-linux-gnu-x32" },
.{ .arch = .x86_64, .os = .linux, .abi = .musl },
.{ .arch = .x86_64, .os = .linux, .abi = .muslx32 },
.{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } },
Expand All @@ -100,6 +102,31 @@ pub fn canBuildLibC(target: std.Target) bool {
return false;
}

/// Returns the subdirectory triple to be used to find the correct glibc for the given `arch`, `os`,
/// and `abi` in an installation directory created by glibc's `build-many-glibcs.py` script.
///
/// `os` must be `.linux` or `.hurd`. `abi` must be a GNU ABI, i.e. `.isGnu()`.
pub fn glibcRuntimeTriple(
allocator: Allocator,
arch: std.Target.Cpu.Arch,
os: std.Target.Os.Tag,
abi: std.Target.Abi,
) Allocator.Error![]const u8 {
assert(abi.isGnu());

for (available_libcs) |libc| {
if (libc.arch == arch and libc.os == os and libc.abi == abi) {
if (libc.glibc_triple) |triple| return allocator.dupe(u8, triple);
}
}

return switch (os) {
.hurd => std.Target.hurdTupleSimple(allocator, arch, abi),
.linux => std.Target.linuxTripleSimple(allocator, arch, os, abi),
else => unreachable,
};
}

pub fn muslArchName(arch: std.Target.Cpu.Arch, abi: std.Target.Abi) [:0]const u8 {
return switch (abi) {
.muslabin32 => "mipsn32",
Expand Down Expand Up @@ -285,3 +312,5 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
}

const std = @import("std");
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
107 changes: 55 additions & 52 deletions tools/process_headers.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,62 +18,61 @@ const assert = std.debug.assert;
const Blake3 = std.crypto.hash.Blake3;

const LibCTarget = struct {
name: []const u8,
arch: Arch,
abi: Abi,
};

const glibc_targets = [_]LibCTarget{
.{ .name = "arc-linux-gnu", .arch = .arc, .abi = .gnu },
.{ .name = "arm-linux-gnueabi", .arch = .arm, .abi = .gnueabi },
.{ .name = "arm-linux-gnueabihf", .arch = .arm, .abi = .gnueabihf },
.{ .name = "armeb-linux-gnueabi", .arch = .armeb, .abi = .gnueabi },
.{ .name = "armeb-linux-gnueabihf", .arch = .armeb, .abi = .gnueabihf },
.{ .name = "aarch64-linux-gnu", .arch = .aarch64, .abi = .gnu },
.{ .name = "aarch64_be-linux-gnu", .arch = .aarch64_be, .abi = .gnu },
.{ .name = "csky-linux-gnuabiv2-soft", .arch = .csky, .abi = .gnueabi },
.{ .name = "csky-linux-gnuabiv2", .arch = .csky, .abi = .gnueabihf },
.{ .name = "loongarch64-linux-gnu-lp64d", .arch = .loongarch64, .abi = .gnu },
.{ .name = "loongarch64-linux-gnu-lp64s", .arch = .loongarch64, .abi = .gnusf },
.{ .name = "m68k-linux-gnu", .arch = .m68k, .abi = .gnu },
.{ .name = "mips-linux-gnu", .arch = .mips, .abi = .gnueabihf },
.{ .name = "mips-linux-gnu-soft", .arch = .mips, .abi = .gnueabi },
.{ .name = "mipsel-linux-gnu-soft", .arch = .mipsel, .abi = .gnueabi },
.{ .name = "mipsel-linux-gnu", .arch = .mipsel, .abi = .gnueabihf },
.{ .name = "mips64-linux-gnu-n64", .arch = .mips64, .abi = .gnuabi64 },
.{ .name = "mips64-linux-gnu-n32", .arch = .mips64, .abi = .gnuabin32 },
.{ .name = "mips64el-linux-gnu-n64", .arch = .mips64el, .abi = .gnuabi64 },
.{ .name = "mips64el-linux-gnu-n32", .arch = .mips64el, .abi = .gnuabin32 },
.{ .name = "powerpc-linux-gnu-soft", .arch = .powerpc, .abi = .gnueabi },
.{ .name = "powerpc-linux-gnu", .arch = .powerpc, .abi = .gnueabihf },
.{ .name = "powerpc64-linux-gnu", .arch = .powerpc64, .abi = .gnu },
.{ .name = "powerpc64le-linux-gnu", .arch = .powerpc64le, .abi = .gnu },
.{ .name = "riscv32-linux-gnu-rv32imafdc-ilp32d", .arch = .riscv32, .abi = .gnu },
.{ .name = "riscv64-linux-gnu-rv64imafdc-lp64d", .arch = .riscv64, .abi = .gnu },
.{ .name = "s390x-linux-gnu", .arch = .s390x, .abi = .gnu },
.{ .name = "sparcv9-linux-gnu", .arch = .sparc, .abi = .gnu },
.{ .name = "sparc64-linux-gnu", .arch = .sparc64, .abi = .gnu },
.{ .name = "i686-linux-gnu", .arch = .x86, .abi = .gnu },
.{ .name = "x86_64-linux-gnu", .arch = .x86_64, .abi = .gnu },
.{ .name = "x86_64-linux-gnu-x32", .arch = .x86_64, .abi = .gnux32 },
.{ .arch = .arc, .abi = .gnu },
.{ .arch = .arm, .abi = .gnueabi },
.{ .arch = .arm, .abi = .gnueabihf },
.{ .arch = .armeb, .abi = .gnueabi },
.{ .arch = .armeb, .abi = .gnueabihf },
.{ .arch = .aarch64, .abi = .gnu },
.{ .arch = .aarch64_be, .abi = .gnu },
.{ .arch = .csky, .abi = .gnueabi },
.{ .arch = .csky, .abi = .gnueabihf },
.{ .arch = .loongarch64, .abi = .gnu },
.{ .arch = .loongarch64, .abi = .gnusf },
.{ .arch = .m68k, .abi = .gnu },
.{ .arch = .mips, .abi = .gnueabi },
.{ .arch = .mips, .abi = .gnueabihf },
.{ .arch = .mipsel, .abi = .gnueabi },
.{ .arch = .mipsel, .abi = .gnueabihf },
.{ .arch = .mips64, .abi = .gnuabi64 },
.{ .arch = .mips64, .abi = .gnuabin32 },
.{ .arch = .mips64el, .abi = .gnuabi64 },
.{ .arch = .mips64el, .abi = .gnuabin32 },
.{ .arch = .powerpc, .abi = .gnueabi },
.{ .arch = .powerpc, .abi = .gnueabihf },
.{ .arch = .powerpc64, .abi = .gnu },
.{ .arch = .powerpc64le, .abi = .gnu },
.{ .arch = .riscv32, .abi = .gnu },
.{ .arch = .riscv64, .abi = .gnu },
.{ .arch = .s390x, .abi = .gnu },
.{ .arch = .sparc, .abi = .gnu },
.{ .arch = .sparc64, .abi = .gnu },
.{ .arch = .x86, .abi = .gnu },
.{ .arch = .x86_64, .abi = .gnu },
.{ .arch = .x86_64, .abi = .gnux32 },
};

const musl_targets = [_]LibCTarget{
.{ .name = "arm", .arch = .arm, .abi = .musl },
.{ .name = "aarch64", .arch = .aarch64, .abi = .musl },
.{ .name = "loongarch64", .arch = .loongarch64, .abi = .musl },
.{ .name = "m68k", .arch = .m68k, .abi = .musl },
.{ .name = "mips", .arch = .mips, .abi = .musl },
.{ .name = "mips64", .arch = .mips64, .abi = .musl },
.{ .name = "mipsn32", .arch = .mips64, .abi = .muslabin32 },
.{ .name = "powerpc", .arch = .powerpc, .abi = .musl },
.{ .name = "powerpc64", .arch = .powerpc64, .abi = .musl },
.{ .name = "riscv32", .arch = .riscv32, .abi = .musl },
.{ .name = "riscv64", .arch = .riscv64, .abi = .musl },
.{ .name = "s390x", .arch = .s390x, .abi = .musl },
.{ .name = "i386", .arch = .x86, .abi = .musl },
.{ .name = "x86_64", .arch = .x86_64, .abi = .musl },
.{ .name = "x32", .arch = .x86_64, .abi = .muslx32 },
.{ .arch = .arm, .abi = .musl },
.{ .arch = .aarch64, .abi = .musl },
.{ .arch = .loongarch64, .abi = .musl },
.{ .arch = .m68k, .abi = .musl },
.{ .arch = .mips, .abi = .musl },
.{ .arch = .mips64, .abi = .musl },
.{ .arch = .mips64, .abi = .muslabin32 },
.{ .arch = .powerpc, .abi = .musl },
.{ .arch = .powerpc64, .abi = .musl },
.{ .arch = .riscv32, .abi = .musl },
.{ .arch = .riscv64, .abi = .musl },
.{ .arch = .s390x, .abi = .musl },
.{ .arch = .x86, .abi = .musl },
.{ .arch = .x86_64, .abi = .musl },
.{ .arch = .x86_64, .abi = .muslx32 },
};

const DestTarget = struct {
Expand Down Expand Up @@ -174,6 +173,10 @@ pub fn main() !void {
var hasher = Blake3.init(.{});

for (libc_targets) |libc_target| {
const libc_dir = switch (vendor) {
.glibc => try std.zig.target.glibcRuntimeTriple(allocator, libc_target.arch, .linux, libc_target.abi),
.musl => std.zig.target.muslArchName(libc_target.arch, libc_target.abi),
};
const dest_target = DestTarget{
.arch = libc_target.arch,
.os = .linux,
Expand All @@ -182,8 +185,8 @@ pub fn main() !void {

search: for (search_paths.items) |search_path| {
const sub_path = switch (vendor) {
.glibc => &[_][]const u8{ search_path, libc_target.name, "usr", "include" },
.musl => &[_][]const u8{ search_path, libc_target.name, "usr", "local", "musl", "include" },
.glibc => &[_][]const u8{ search_path, libc_dir, "usr", "include" },
.musl => &[_][]const u8{ search_path, libc_dir, "usr", "local", "musl", "include" },
};
const target_include_dir = try std.fs.path.join(allocator, sub_path);
var dir_stack = std.ArrayList([]const u8).init(allocator);
Expand Down Expand Up @@ -219,7 +222,7 @@ pub fn main() !void {
max_bytes_saved += raw_bytes.len;
gop.value_ptr.hit_count += 1;
std.debug.print("duplicate: {s} {s} ({:2})\n", .{
libc_target.name,
libc_dir,
rel_path,
std.fmt.fmtIntSizeDec(raw_bytes.len),
});
Expand All @@ -246,7 +249,7 @@ pub fn main() !void {
}
break;
} else {
std.debug.print("warning: libc target not found: {s}\n", .{libc_target.name});
std.debug.print("warning: libc target not found: {s}\n", .{libc_dir});
}
}
std.debug.print("summary: {:2} could be reduced to {:2}\n", .{
Expand Down

0 comments on commit d48611b

Please sign in to comment.