Commit 8818dc6213

Alex Rønne Petersen <alex@alexrp.com>
2024-10-07 00:29:57
std.zig.system: Fix detectAbiAndDynamicLinker() for non-Linux/Hurd ELF hosts.
Since we exclude Abi.none from the list of ABIs to be tested, it means that Abi.gnu, which happens to be the first in the list, always gets picked for hosts where the dynamic linker path does not depend on the ABI component of the triple. Such hosts include all the BSDs, Haiku, Serenity, Solaris, etc. To fix this, use DynamicLinker.kind() to determine whether this whole exercise even makes sense. If it doesn't, as is the case on every OS other than Linux and Hurd, we'll just fall back to Abi.default() which will try to pick a sensible default based on the arch and OS components. This detection logic still has plenty of room for improvement, but is at least a notable step up from confusingly detecting Abi.gnu ~everywhere. Closes #9089.
1 parent 27c85e5
Changed files (1)
lib
std
lib/std/zig/system.zig
@@ -996,26 +996,33 @@ fn detectAbiAndDynamicLinker(
     };
     var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
     var ld_info_list_len: usize = 0;
-    const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
-
-    for (all_abis) |abi| {
-        // This may be a nonsensical parameter. We detect this with
-        // error.UnknownDynamicLinkerPath and skip adding it to `ld_info_list`.
-        const target: Target = .{
-            .cpu = cpu,
-            .os = os,
-            .abi = abi,
-            .ofmt = ofmt,
-        };
-        const ld = target.standardDynamicLinkerPath();
-        if (ld.get() == null) continue;
 
-        ld_info_list_buffer[ld_info_list_len] = .{
-            .ld = ld,
-            .abi = abi,
-        };
-        ld_info_list_len += 1;
+    switch (Target.DynamicLinker.kind(os.tag)) {
+        // The OS has no dynamic linker. Leave the list empty and rely on `Abi.default()` to pick
+        // something sensible in `abiAndDynamicLinkerFromFile()`.
+        .none => {},
+        // The OS has a system-wide dynamic linker. Unfortunately, this implies that there's no
+        // useful ABI information that we can glean from it merely being present. That means the
+        // best we can do for this case (for now) is also `Abi.default()`.
+        .arch_os => {},
+        // The OS can have different dynamic linker paths depending on libc/ABI. In this case, we
+        // need to gather all the valid arch/OS/ABI combinations. `abiAndDynamicLinkerFromFile()`
+        // will then look for a dynamic linker with a matching path on the system and pick the ABI
+        // we associated it with here.
+        .arch_os_abi => for (all_abis) |abi| {
+            const ld = Target.DynamicLinker.standard(cpu, os, abi);
+
+            // Does the generated target triple actually have a standard dynamic linker path?
+            if (ld.get() == null) continue;
+
+            ld_info_list_buffer[ld_info_list_len] = .{
+                .ld = ld,
+                .abi = abi,
+            };
+            ld_info_list_len += 1;
+        },
     }
+
     const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
 
     // Best case scenario: the executable is dynamically linked, and we can iterate