Commit 35f30558ad

Alex Rønne Petersen <alex@alexrp.com>
2025-05-06 01:52:47
std.Build: Rename --glibc-runtimes to --libc-runtimes and enable it for musl.
1 parent a14352b
Changed files (4)
lib
compiler
std
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
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) {
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) {
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),