Function standard [src]

The strictness of this function depends on the value of kind(os.tag): .none: Ignores all arguments and just returns none. .arch_os: Ignores abi and returns the dynamic linker matching cpu and os. .arch_os_abi: Returns the dynamic linker matching cpu, os, and abi. In the case of .arch_os in particular, callers should be aware that a valid dynamic linker being returned only means that the cpu + os combination represents a platform that actually exists and which has an established dynamic linker path that does not change with the ABI; it does not necessarily mean that abi makes any sense at all for that platform. The responsibility for determining whether abi is valid in this case rests with the caller. Abi.default() can be used to pick a best-effort default ABI for such platforms.

Prototype

pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker

Parameters

cpu: Cpuos: Osabi: Abi

Source

pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker { return switch (os.tag) { .fuchsia => switch (cpu.arch) { .aarch64, .riscv64, .x86_64, => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename. else => none, }, .haiku => switch (cpu.arch) { .arm, .thumb, .aarch64, .m68k, .powerpc, .riscv64, .sparc64, .x86, .x86_64, => init("/system/runtime_loader"), else => none, }, .hurd => switch (cpu.arch) { .aarch64, .aarch64_be, => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{ @tagName(arch), switch (abi) { .gnu => "", .gnuilp32 => "_ilp32", else => return none, }, }), .x86 => if (abi == .gnu) init("/lib/ld.so.1") else none, .x86_64 => initFmt("/lib/ld-{s}.so.1", .{switch (abi) { .gnu => "x86-64", .gnux32 => "x32", else => return none, }}), else => none, }, .linux => if (abi.isAndroid()) switch (cpu.arch) { .arm, .thumb, => if (abi == .androideabi) init("/system/bin/linker") else none, .aarch64, .riscv64, .x86, .x86_64, => if (abi == .android) initFmt("/system/bin/linker{s}", .{ if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "", }) else none, else => none, } else if (abi.isMusl()) switch (cpu.arch) { .arm, .armeb, .thumb, .thumbeb, => |arch| initFmt("/lib/ld-musl-arm{s}{s}.so.1", .{ if (arch == .armeb or arch == .thumbeb) "eb" else "", switch (abi) { .musleabi => "", .musleabihf => "hf", else => return none, }, }), .aarch64, .aarch64_be, .loongarch64, // TODO: `-sp` and `-sf` ABI support in LLVM 20. .m68k, .powerpc64, .powerpc64le, .s390x, => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}.so.1", .{@tagName(arch)}) else none, .mips, .mipsel, => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{ if (mips.featureSetHas(cpu.features, .mips32r6)) "r6" else "", if (arch == .mipsel) "el" else "", switch (abi) { .musleabi => "-sf", .musleabihf => "", else => return none, }, }), .mips64, .mips64el, => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{ switch (abi) { .muslabi64 => "64", .muslabin32 => "n32", else => return none, }, if (mips.featureSetHas(cpu.features, .mips64r6)) "r6" else "", if (arch == .mips64el) "el" else "", }), .powerpc => initFmt("/lib/ld-musl-powerpc{s}.so.1", .{switch (abi) { .musleabi => "-sf", .musleabihf => "", else => return none, }}), .riscv32, .riscv64, => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{ @tagName(arch), if (riscv.featureSetHas(cpu.features, .d)) "" else if (riscv.featureSetHas(cpu.features, .f)) "-sp" else "-sf", }) else none, .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none, .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) { .musl => "x86_64", .muslx32 => "x32", else => return none, }}), else => none, } else if (abi.isGnu()) switch (cpu.arch) { // TODO: `eb` architecture support. // TODO: `700` ABI support. .arc => if (abi == .gnu) init("/lib/ld-linux-arc.so.2") else none, .arm, .armeb, .thumb, .thumbeb, => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi) { .gnueabi => "", .gnueabihf => "-armhf", else => return none, }}), .aarch64, .aarch64_be, => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{ @tagName(arch), switch (abi) { .gnu => "", .gnuilp32 => "_ilp32", else => return none, }, }), // TODO: `-be` architecture support. .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{switch (abi) { .gnueabi => "", .gnueabihf => "-hf", else => return none, }}), .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) { .gnu => "lp64d", .gnuf32 => "lp64f", .gnusf => "lp64s", else => return none, }}), .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none, .mips, .mipsel, => switch (abi) { .gnueabi, .gnueabihf, => initFmt("/lib/ld{s}.so.1", .{ if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "", }), else => none, }, .mips64, .mips64el, => initFmt("/lib{s}/ld{s}.so.1", .{ switch (abi) { .gnuabi64 => "64", .gnuabin32 => "32", else => return none, }, if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "", }), .powerpc => switch (abi) { .gnueabi, .gnueabihf, => init("/lib/ld.so.1"), else => none, }, // TODO: ELFv2 ABI (`/lib64/ld64.so.2`) opt-in support. .powerpc64 => if (abi == .gnu) init("/lib64/ld64.so.1") else none, .powerpc64le => if (abi == .gnu) init("/lib64/ld64.so.2") else none, .riscv32, .riscv64, => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{s}{s}.so.1", .{ switch (arch) { .riscv32 => "riscv32-ilp32", .riscv64 => "riscv64-lp64", else => unreachable, }, if (riscv.featureSetHas(cpu.features, .d)) "d" else if (riscv.featureSetHas(cpu.features, .f)) "f" else "", }) else none, .s390x => if (abi == .gnu) init("/lib/ld64.so.1") else none, .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none, .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none, .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none, .x86_64 => switch (abi) { .gnu => init("/lib64/ld-linux-x86-64.so.2"), .gnux32 => init("/libx32/ld-linux-x32.so.2"), else => none, }, .xtensa => if (abi == .gnu) init("/lib/ld.so.1") else none, else => none, } else none, // Not a known Linux libc. .serenity => switch (cpu.arch) { .aarch64, .riscv64, .x86_64, => init("/usr/lib/Loader.so"), else => none, }, .dragonfly => if (cpu.arch == .x86_64) initFmt("{s}/libexec/ld-elf.so.2", .{ if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false) "" else "/usr", }) else none, .freebsd => switch (cpu.arch) { .arm, .armeb, .thumb, .thumbeb, .aarch64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le, .riscv64, .sparc64, .x86, .x86_64, => initFmt("{s}/libexec/ld-elf.so.1", .{ if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false) "" else "/usr", }), else => none, }, .netbsd => switch (cpu.arch) { .arm, .armeb, .thumb, .thumbeb, .aarch64, .aarch64_be, .m68k, .mips, .mipsel, .mips64, .mips64el, .powerpc, .riscv64, .sparc, .sparc64, .x86, .x86_64, => init("/libexec/ld.elf_so"), else => none, }, .openbsd => switch (cpu.arch) { .arm, .thumb, .aarch64, .mips64, .mips64el, .powerpc, .powerpc64, .riscv64, .sparc64, .x86, .x86_64, => init("/usr/libexec/ld.so"), else => none, }, .driverkit, .ios, .macos, .tvos, .visionos, .watchos, => switch (cpu.arch) { .aarch64, .x86_64, => init("/usr/lib/dyld"), else => none, }, .illumos, .solaris, => switch (cpu.arch) { .sparc, .sparc64, .x86, .x86_64, => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, .none) == 64) "64/" else ""}), else => none, }, // Operating systems in this list have been verified as not having a standard // dynamic linker path. .freestanding, .other, .contiki, .elfiamcu, .hermit, .aix, .plan9, .rtems, .zos, .uefi, .windows, .emscripten, .wasi, .amdhsa, .amdpal, .cuda, .mesa3d, .nvcl, .opencl, .opengl, .vulkan, => none, // TODO go over each item in this list and either move it to the above list, or // implement the standard dynamic linker path code for it. .ps3, .ps4, .ps5, => none, } catch unreachable; }