diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 2ba7631cf4..668c60361f 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -241,8 +241,9 @@ pub fn main() !void { // but it is handled by the parent process. The build runner // only sees this flag. graph.system_package_mode = true; - } else if (mem.eql(u8, arg, "--glibc-runtimes")) { - builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx); + } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) { + // --glibc-runtimes was the old name of the flag; kept for compatibility for now. + builder.libc_runtimes_dir = nextArgOrFatal(args, &arg_idx); } else if (mem.eql(u8, arg, "--verbose-link")) { builder.verbose_link = true; } else if (mem.eql(u8, arg, "--verbose-air")) { @@ -1279,9 +1280,10 @@ fn usage(b: *std.Build, out_stream: anytype) !void { \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute \\ foreign-architecture programs on Linux hosts \\ (default: no) - \\ --glibc-runtimes [path] Enhances QEMU integration by providing glibc built - \\ for multiple foreign architectures, allowing - \\ execution of non-native programs that link with glibc. + \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc + \\ (e.g. glibc or musl) built for multiple foreign + \\ architectures, allowing execution of non-native + \\ programs that link with libc. \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on \\ ARM64 macOS hosts. (default: no) \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 8ce4fe40e3..ea22fde4ec 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -79,7 +79,8 @@ enable_wine: bool = false, /// this will be the directory $glibc-build-dir/install/glibcs /// Given the example of the aarch64 target, this is the directory /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`. -glibc_runtimes_dir: ?[]const u8 = null, +/// Also works for dynamic musl. +libc_runtimes_dir: ?[]const u8 = null, dep_prefix: []const u8 = "", @@ -390,7 +391,7 @@ fn createChildOnly( .enable_rosetta = parent.enable_rosetta, .enable_wasmtime = parent.enable_wasmtime, .enable_wine = parent.enable_wine, - .glibc_runtimes_dir = parent.glibc_runtimes_dir, + .libc_runtimes_dir = parent.libc_runtimes_dir, .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), .modules = .init(allocator), .named_writefiles = .init(allocator), diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 3d0b0a7068..eede464ab6 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1026,11 +1026,11 @@ fn runCommand( } const root_target = exe.rootModuleTarget(); - const need_cross_glibc = root_target.isGnuLibC() and - exe.is_linking_libc; + const need_cross_libc = exe.is_linking_libc and + (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic)); const other_target = exe.root_module.resolved_target.?.result; switch (std.zig.system.getExternalExecutor(b.graph.host.result, &other_target, .{ - .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, + .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { .native, .rosetta => { @@ -1047,31 +1047,29 @@ fn runCommand( }, .qemu => |bin_name| { if (b.enable_qemu) { - const glibc_dir_arg = if (need_cross_glibc) - b.glibc_runtimes_dir orelse - return failForeign(run, "--glibc-runtimes", argv[0], exe) - else - null; - try interp_argv.append(bin_name); - if (glibc_dir_arg) |dir| { - try interp_argv.append("-L"); - 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, - ), - })); + if (need_cross_libc) { + if (b.libc_runtimes_dir) |dir| { + try interp_argv.append("-L"); + try interp_argv.append(b.pathJoin(&.{ + dir, + try if (root_target.isGnuLibC()) std.zig.target.glibcRuntimeTriple( + b.allocator, + root_target.cpu.arch, + root_target.os.tag, + root_target.abi, + ) else if (root_target.isMuslLibC()) std.zig.target.muslRuntimeTriple( + b.allocator, + root_target.cpu.arch, + root_target.abi, + ) else unreachable, + })); + } else return failForeign(run, "--libc-runtimes", argv[0], exe); } try interp_argv.appendSlice(argv); - } else { - return failForeign(run, "-fqemu", argv[0], exe); - } + } else return failForeign(run, "-fqemu", argv[0], exe); }, .darling => |bin_name| { if (b.enable_darling) { diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 4b20c132a6..c77d69d89d 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -131,6 +131,20 @@ pub fn glibcRuntimeTriple( }; } +/// Returns the subdirectory triple to be used to find the correct musl for the given `arch` and +/// `abi` in an installation directory. +/// +/// `abi` must be a musl ABI, i.e. `.isMusl()`. +pub fn muslRuntimeTriple( + allocator: Allocator, + arch: std.Target.Cpu.Arch, + abi: std.Target.Abi, +) Allocator.Error![]const u8 { + assert(abi.isMusl()); + + return std.Target.linuxTripleSimple(allocator, arch, .linux, abi); +} + pub fn osArchName(target: std.Target) [:0]const u8 { return switch (target.os.tag) { .linux => switch (target.cpu.arch) {