authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-07 00:29:57+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-26 22:00:49+02:00
log8818dc62131979cb29efe7a9f2a2ebd17583cd4a
tree5316af595ee662e250f1f7de73c2bda9ba3f2098
parent27c85e5969f01853b2437d56ddc7a7eee9bf35d0
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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 files changed, 25 insertions(+), 18 deletions(-)

lib/std/zig/system.zig+25-18
...@@ -996,26 +996,33 @@ fn detectAbiAndDynamicLinker(...@@ -996,26 +996,33 @@ fn detectAbiAndDynamicLinker(
996 };996 };
997 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;997 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
998 var ld_info_list_len: usize = 0;998 var ld_info_list_len: usize = 0;
999 const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
1000
1001 for (all_abis) |abi| {
1002 // This may be a nonsensical parameter. We detect this with
1003 // error.UnknownDynamicLinkerPath and skip adding it to `ld_info_list`.
1004 const target: Target = .{
1005 .cpu = cpu,
1006 .os = os,
1007 .abi = abi,
1008 .ofmt = ofmt,
1009 };
1010 const ld = target.standardDynamicLinkerPath();
1011 if (ld.get() == null) continue;
1012999
1013 ld_info_list_buffer[ld_info_list_len] = .{1000 switch (Target.DynamicLinker.kind(os.tag)) {
1014 .ld = ld,1001 // The OS has no dynamic linker. Leave the list empty and rely on `Abi.default()` to pick
1015 .abi = abi,1002 // something sensible in `abiAndDynamicLinkerFromFile()`.
1016 };1003 .none => {},
1017 ld_info_list_len += 1;1004 // The OS has a system-wide dynamic linker. Unfortunately, this implies that there's no
1005 // useful ABI information that we can glean from it merely being present. That means the
1006 // best we can do for this case (for now) is also `Abi.default()`.
1007 .arch_os => {},
1008 // The OS can have different dynamic linker paths depending on libc/ABI. In this case, we
1009 // need to gather all the valid arch/OS/ABI combinations. `abiAndDynamicLinkerFromFile()`
1010 // will then look for a dynamic linker with a matching path on the system and pick the ABI
1011 // we associated it with here.
1012 .arch_os_abi => for (all_abis) |abi| {
1013 const ld = Target.DynamicLinker.standard(cpu, os, abi);
1014
1015 // Does the generated target triple actually have a standard dynamic linker path?
1016 if (ld.get() == null) continue;
1017
1018 ld_info_list_buffer[ld_info_list_len] = .{
1019 .ld = ld,
1020 .abi = abi,
1021 };
1022 ld_info_list_len += 1;
1023 },
1018 }1024 }
1025
1019 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];1026 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
10201027
1021 // Best case scenario: the executable is dynamically linked, and we can iterate1028 // Best case scenario: the executable is dynamically linked, and we can iterate