zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 8818dc62131979cb29efe7a9f2a2ebd17583cd4a (tree)
parent 27c85e5969f01853b2437d56ddc7a7eee9bf35d0
Author: Alex Rønne Petersen <alex@alexrp.com>
Date:   Mon,  7 Oct 2024 00:29:57 +0200

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.

Diffstat:
Mlib/std/zig/system.zig | 43+++++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/lib/std/zig/system.zig b/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