Function getExternalExecutor [src]
Return whether or not the given host is capable of running executables of
the other target.
Prototype
pub fn getExternalExecutor( host: std.Target, candidate: *const std.Target, options: GetExternalExecutorOptions, ) Executor
Parameters
host: std.Target
candidate: *const std.Target
options: GetExternalExecutorOptions
Source
pub fn getExternalExecutor(
host: 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 (std.Target.sparc.featureSetHas(candidate.cpu.features, .v9))
"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,
};
}
switch (candidate.os.tag) {
.windows => {
if (options.allow_wine) {
// x86_64 wine does not support emulating aarch64-windows and
// vice versa.
if (candidate.cpu.arch != builtin.cpu.arch and
!(candidate.cpu.arch == .thumb and builtin.cpu.arch == .aarch64) and
!(candidate.cpu.arch == .x86 and builtin.cpu.arch == .x86_64))
{
return bad_result;
}
switch (candidate.ptrBitWidth()) {
32 => return Executor{ .wine = "wine" },
64 => return Executor{ .wine = "wine64" },
else => return bad_result,
}
}
return bad_result;
},
.wasi => {
if (options.allow_wasmtime) {
switch (candidate.ptrBitWidth()) {
32 => return Executor{ .wasmtime = "wasmtime" },
else => return bad_result,
}
}
return bad_result;
},
.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 != builtin.cpu.arch) {
return bad_result;
}
return Executor{ .darling = "darling" };
}
return bad_result;
},
else => return bad_result,
}
}