Function getExternalExecutor [src]

Return whether or not the given host is capable of running executables of the other target.

Prototype

pub fn getExternalExecutor( host: *const std.Target, candidate: *const std.Target, options: GetExternalExecutorOptions, ) Executor

Parameters

host: *const std.Targetcandidate: *const std.Targetoptions: GetExternalExecutorOptions

Source

pub fn getExternalExecutor( host: *const std.Target, candidate: *const std.Target, options: GetExternalExecutorOptions, ) Executor { const os_match = host.os.tag == candidate.os.tag; const cpu_ok = cpu_ok: { if (host.cpu.arch == candidate.cpu.arch) break :cpu_ok true; if (host.cpu.arch == .x86_64 and candidate.cpu.arch == .x86) break :cpu_ok true; if (host.cpu.arch == .aarch64 and candidate.cpu.arch == .arm) break :cpu_ok true; if (host.cpu.arch == .aarch64_be and candidate.cpu.arch == .armeb) break :cpu_ok true; // TODO additionally detect incompatible CPU features. // Note that in some cases the OS kernel will emulate missing CPU features // when an illegal instruction is encountered. break :cpu_ok false; }; var bad_result: Executor = .bad_os_or_cpu; if (os_match and cpu_ok) native: { if (options.link_libc) { if (candidate.dynamic_linker.get()) |candidate_dl| { fs.cwd().access(candidate_dl, .{}) catch { bad_result = .{ .bad_dl = candidate_dl }; break :native; }; } } return .native; } // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2 // to emulate the foreign architecture. if (options.allow_rosetta and os_match and host.os.tag == .macos and host.cpu.arch == .aarch64) { switch (candidate.cpu.arch) { .x86_64 => return .rosetta, else => return bad_result, } } // If the OS matches, we can use QEMU to emulate a foreign architecture. if (options.allow_qemu and os_match and (!cpu_ok or options.qemu_fixes_dl)) { return switch (candidate.cpu.arch) { .aarch64 => Executor{ .qemu = "qemu-aarch64" }, .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, .arm, .thumb => Executor{ .qemu = "qemu-arm" }, .armeb, .thumbeb => Executor{ .qemu = "qemu-armeb" }, .hexagon => Executor{ .qemu = "qemu-hexagon" }, .loongarch64 => Executor{ .qemu = "qemu-loongarch64" }, .m68k => Executor{ .qemu = "qemu-m68k" }, .mips => Executor{ .qemu = "qemu-mips" }, .mipsel => Executor{ .qemu = "qemu-mipsel" }, .mips64 => Executor{ .qemu = switch (candidate.abi) { .gnuabin32, .muslabin32 => "qemu-mipsn32", else => "qemu-mips64", }, }, .mips64el => Executor{ .qemu = switch (candidate.abi) { .gnuabin32, .muslabin32 => "qemu-mipsn32el", else => "qemu-mips64el", }, }, .powerpc => Executor{ .qemu = "qemu-ppc" }, .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, .riscv32 => Executor{ .qemu = "qemu-riscv32" }, .riscv64 => Executor{ .qemu = "qemu-riscv64" }, .s390x => Executor{ .qemu = "qemu-s390x" }, .sparc => Executor{ .qemu = if (candidate.cpu.has(.sparc, .v8plus)) "qemu-sparc32plus" else "qemu-sparc", }, .sparc64 => Executor{ .qemu = "qemu-sparc64" }, .x86 => Executor{ .qemu = "qemu-i386" }, .x86_64 => switch (candidate.abi) { .gnux32, .muslx32 => return bad_result, else => Executor{ .qemu = "qemu-x86_64" }, }, .xtensa => Executor{ .qemu = "qemu-xtensa" }, else => return bad_result, }; } if (options.allow_wasmtime and candidate.cpu.arch.isWasm()) { return Executor{ .wasmtime = "wasmtime" }; } switch (candidate.os.tag) { .windows => { if (options.allow_wine) { const wine_supported = switch (candidate.cpu.arch) { .thumb => switch (host.cpu.arch) { .arm, .thumb, .aarch64 => true, else => false, }, .aarch64 => host.cpu.arch == .aarch64, .x86 => host.cpu.arch.isX86(), .x86_64 => host.cpu.arch == .x86_64, else => false, }; return if (wine_supported) Executor{ .wine = "wine" } else bad_result; } return bad_result; }, .driverkit, .macos => { if (options.allow_darling) { // This check can be loosened once darling adds a QEMU-based emulation // layer for non-host architectures: // https://github.com/darlinghq/darling/issues/863 if (candidate.cpu.arch != host.cpu.arch) { return bad_result; } return Executor{ .darling = "darling" }; } return bad_result; }, else => return bad_result, } }