mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Functions like isMinGW() and isGnuLibC() have a good reason to exist: They look at multiple components of the target. But functions like isWasm(), isDarwin(), isGnu(), etc only exist to save 4-8 characters. I don't think this is a good enough reason to keep them, especially given that: * It's not immediately obvious to a reader whether target.isDarwin() means the same thing as target.os.tag.isDarwin() precisely because isMinGW() and similar functions *do* look at multiple components. * It's not clear where we would draw the line. The logical conclusion before this commit would be to also wrap Arch.isX86(), Os.Tag.isSolarish(), Abi.isOpenHarmony(), etc... this obviously quickly gets out of hand. * It's nice to just have a single correct way of doing something.
638 lines
28 KiB
Zig
Vendored
638 lines
28 KiB
Zig
Vendored
const std = @import("std");
|
|
const Toolchain = @import("../Toolchain.zig");
|
|
const target_util = @import("../target.zig");
|
|
const system_defaults = @import("system_defaults");
|
|
const GCCVersion = @import("GCCVersion.zig");
|
|
const Multilib = @import("Multilib.zig");
|
|
|
|
const GCCDetector = @This();
|
|
|
|
is_valid: bool = false,
|
|
install_path: []const u8 = "",
|
|
parent_lib_path: []const u8 = "",
|
|
version: GCCVersion = .{},
|
|
gcc_triple: []const u8 = "",
|
|
selected: Multilib = .{},
|
|
biarch_sibling: ?Multilib = null,
|
|
|
|
pub fn deinit(self: *GCCDetector) void {
|
|
if (!self.is_valid) return;
|
|
}
|
|
|
|
pub fn appendToolPath(self: *const GCCDetector, tc: *Toolchain) !void {
|
|
if (!self.is_valid) return;
|
|
return tc.addPathFromComponents(&.{
|
|
self.parent_lib_path,
|
|
"..",
|
|
self.gcc_triple,
|
|
"bin",
|
|
}, .program);
|
|
}
|
|
|
|
fn addDefaultGCCPrefixes(prefixes: *std.ArrayListUnmanaged([]const u8), tc: *const Toolchain) !void {
|
|
const sysroot = tc.getSysroot();
|
|
const target = tc.getTarget();
|
|
if (sysroot.len == 0 and target.os.tag == .linux and tc.filesystem.exists("/opt/rh")) {
|
|
prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-12/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-11/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-10/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-12/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-11/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-10/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-9/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-8/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-7/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-6/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-4/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-3/root/usr");
|
|
prefixes.appendAssumeCapacity("/opt/rh/devtoolset-2/root/usr");
|
|
}
|
|
if (sysroot.len == 0) {
|
|
prefixes.appendAssumeCapacity("/usr");
|
|
} else {
|
|
var usr_path = try tc.arena.alloc(u8, 4 + sysroot.len);
|
|
@memcpy(usr_path[0..4], "/usr");
|
|
@memcpy(usr_path[4..], sysroot);
|
|
prefixes.appendAssumeCapacity(usr_path);
|
|
}
|
|
}
|
|
|
|
fn collectLibDirsAndTriples(
|
|
tc: *Toolchain,
|
|
lib_dirs: *std.ArrayListUnmanaged([]const u8),
|
|
triple_aliases: *std.ArrayListUnmanaged([]const u8),
|
|
biarch_libdirs: *std.ArrayListUnmanaged([]const u8),
|
|
biarch_triple_aliases: *std.ArrayListUnmanaged([]const u8),
|
|
) !void {
|
|
const AArch64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const AArch64Triples: [4][]const u8 = .{ "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", "aarch64-suse-linux" };
|
|
const AArch64beLibDirs: [1][]const u8 = .{"/lib"};
|
|
const AArch64beTriples: [2][]const u8 = .{ "aarch64_be-none-linux-gnu", "aarch64_be-linux-gnu" };
|
|
|
|
const ARMLibDirs: [1][]const u8 = .{"/lib"};
|
|
const ARMTriples: [1][]const u8 = .{"arm-linux-gnueabi"};
|
|
const ARMHFTriples: [4][]const u8 = .{ "arm-linux-gnueabihf", "armv7hl-redhat-linux-gnueabi", "armv6hl-suse-linux-gnueabi", "armv7hl-suse-linux-gnueabi" };
|
|
|
|
const ARMebLibDirs: [1][]const u8 = .{"/lib"};
|
|
const ARMebTriples: [1][]const u8 = .{"armeb-linux-gnueabi"};
|
|
const ARMebHFTriples: [2][]const u8 = .{ "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi" };
|
|
|
|
const AVRLibDirs: [1][]const u8 = .{"/lib"};
|
|
const AVRTriples: [1][]const u8 = .{"avr"};
|
|
|
|
const CSKYLibDirs: [1][]const u8 = .{"/lib"};
|
|
const CSKYTriples: [3][]const u8 = .{ "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2" };
|
|
|
|
const X86_64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const X86_64Triples: [11][]const u8 = .{
|
|
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
|
|
"x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
|
|
"x86_64-redhat-linux", "x86_64-suse-linux",
|
|
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
|
|
"x86_64-slackware-linux", "x86_64-unknown-linux",
|
|
"x86_64-amazon-linux",
|
|
};
|
|
const X32Triples: [2][]const u8 = .{ "x86_64-linux-gnux32", "x86_64-pc-linux-gnux32" };
|
|
const X32LibDirs: [2][]const u8 = .{ "/libx32", "/lib" };
|
|
const X86LibDirs: [2][]const u8 = .{ "/lib32", "/lib" };
|
|
const X86Triples: [9][]const u8 = .{
|
|
"i586-linux-gnu", "i686-linux-gnu", "i686-pc-linux-gnu",
|
|
"i386-redhat-linux6E", "i686-redhat-linux", "i386-redhat-linux",
|
|
"i586-suse-linux", "i686-montavista-linux", "i686-gnu",
|
|
};
|
|
|
|
const LoongArch64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const LoongArch64Triples: [2][]const u8 = .{ "loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu" };
|
|
|
|
const M68kLibDirs: [1][]const u8 = .{"/lib"};
|
|
const M68kTriples: [3][]const u8 = .{ "m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux" };
|
|
|
|
const MIPSLibDirs: [2][]const u8 = .{ "/libo32", "/lib" };
|
|
const MIPSTriples: [5][]const u8 = .{
|
|
"mips-linux-gnu", "mips-mti-linux",
|
|
"mips-mti-linux-gnu", "mips-img-linux-gnu",
|
|
"mipsisa32r6-linux-gnu",
|
|
};
|
|
const MIPSELLibDirs: [2][]const u8 = .{ "/libo32", "/lib" };
|
|
const MIPSELTriples: [3][]const u8 = .{ "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu" };
|
|
|
|
const MIPS64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const MIPS64Triples: [6][]const u8 = .{
|
|
"mips64-linux-gnu", "mips-mti-linux-gnu",
|
|
"mips-img-linux-gnu", "mips64-linux-gnuabi64",
|
|
"mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64",
|
|
};
|
|
const MIPS64ELLibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const MIPS64ELTriples: [6][]const u8 = .{
|
|
"mips64el-linux-gnu", "mips-mti-linux-gnu",
|
|
"mips-img-linux-gnu", "mips64el-linux-gnuabi64",
|
|
"mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64",
|
|
};
|
|
|
|
const MIPSN32LibDirs: [1][]const u8 = .{"/lib32"};
|
|
const MIPSN32Triples: [2][]const u8 = .{ "mips64-linux-gnuabin32", "mipsisa64r6-linux-gnuabin32" };
|
|
const MIPSN32ELLibDirs: [1][]const u8 = .{"/lib32"};
|
|
const MIPSN32ELTriples: [2][]const u8 = .{ "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32" };
|
|
|
|
const MSP430LibDirs: [1][]const u8 = .{"/lib"};
|
|
const MSP430Triples: [1][]const u8 = .{"msp430-elf"};
|
|
|
|
const PPCLibDirs: [2][]const u8 = .{ "/lib32", "/lib" };
|
|
const PPCTriples: [5][]const u8 = .{
|
|
"powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
|
|
// On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a
|
|
// 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".
|
|
"powerpc64-suse-linux", "powerpc-montavista-linuxspe",
|
|
};
|
|
const PPCLELibDirs: [2][]const u8 = .{ "/lib32", "/lib" };
|
|
const PPCLETriples: [3][]const u8 = .{ "powerpcle-linux-gnu", "powerpcle-unknown-linux-gnu", "powerpcle-linux-musl" };
|
|
|
|
const PPC64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const PPC64Triples: [4][]const u8 = .{
|
|
"powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu",
|
|
"powerpc64-suse-linux", "ppc64-redhat-linux",
|
|
};
|
|
const PPC64LELibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const PPC64LETriples: [5][]const u8 = .{
|
|
"powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu",
|
|
"powerpc64le-none-linux-gnu", "powerpc64le-suse-linux",
|
|
"ppc64le-redhat-linux",
|
|
};
|
|
|
|
const RISCV32LibDirs: [2][]const u8 = .{ "/lib32", "/lib" };
|
|
const RISCV32Triples: [3][]const u8 = .{ "riscv32-unknown-linux-gnu", "riscv32-linux-gnu", "riscv32-unknown-elf" };
|
|
const RISCV64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const RISCV64Triples: [3][]const u8 = .{
|
|
"riscv64-unknown-linux-gnu",
|
|
"riscv64-linux-gnu",
|
|
"riscv64-unknown-elf",
|
|
};
|
|
|
|
const SPARCv8LibDirs: [2][]const u8 = .{ "/lib32", "/lib" };
|
|
const SPARCv8Triples: [2][]const u8 = .{ "sparc-linux-gnu", "sparcv8-linux-gnu" };
|
|
const SPARCv9LibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const SPARCv9Triples: [2][]const u8 = .{ "sparc64-linux-gnu", "sparcv9-linux-gnu" };
|
|
|
|
const SystemZLibDirs: [2][]const u8 = .{ "/lib64", "/lib" };
|
|
const SystemZTriples: [5][]const u8 = .{
|
|
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
|
|
"s390x-suse-linux", "s390x-redhat-linux",
|
|
};
|
|
const target = tc.getTarget();
|
|
if (target.os.tag == .solaris) {
|
|
// TODO
|
|
return;
|
|
}
|
|
if (target.abi.isAndroid()) {
|
|
const AArch64AndroidTriples: [1][]const u8 = .{"aarch64-linux-android"};
|
|
const ARMAndroidTriples: [1][]const u8 = .{"arm-linux-androideabi"};
|
|
const MIPSELAndroidTriples: [1][]const u8 = .{"mipsel-linux-android"};
|
|
const MIPS64ELAndroidTriples: [1][]const u8 = .{"mips64el-linux-android"};
|
|
const X86AndroidTriples: [1][]const u8 = .{"i686-linux-android"};
|
|
const X86_64AndroidTriples: [1][]const u8 = .{"x86_64-linux-android"};
|
|
|
|
switch (target.cpu.arch) {
|
|
.aarch64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&AArch64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&AArch64AndroidTriples);
|
|
},
|
|
.arm,
|
|
.thumb,
|
|
=> {
|
|
lib_dirs.appendSliceAssumeCapacity(&ARMLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&ARMAndroidTriples);
|
|
},
|
|
.mipsel => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPSELLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPSELAndroidTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64ELAndroidTriples);
|
|
},
|
|
.mips64el => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPS64ELAndroidTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSELAndroidTriples);
|
|
},
|
|
.x86_64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&X86_64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&X86_64AndroidTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X86LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X86AndroidTriples);
|
|
},
|
|
.x86 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&X86LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&X86AndroidTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64AndroidTriples);
|
|
},
|
|
else => {},
|
|
}
|
|
return;
|
|
}
|
|
switch (target.cpu.arch) {
|
|
.aarch64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&AArch64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&AArch64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&AArch64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&AArch64Triples);
|
|
},
|
|
.aarch64_be => {
|
|
lib_dirs.appendSliceAssumeCapacity(&AArch64beLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&AArch64beTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&AArch64beLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&AArch64beTriples);
|
|
},
|
|
.arm, .thumb => {
|
|
lib_dirs.appendSliceAssumeCapacity(&ARMLibDirs);
|
|
if (target.abi == .gnueabihf) {
|
|
triple_aliases.appendSliceAssumeCapacity(&ARMHFTriples);
|
|
} else {
|
|
triple_aliases.appendSliceAssumeCapacity(&ARMTriples);
|
|
}
|
|
},
|
|
.armeb, .thumbeb => {
|
|
lib_dirs.appendSliceAssumeCapacity(&ARMebLibDirs);
|
|
if (target.abi == .gnueabihf) {
|
|
triple_aliases.appendSliceAssumeCapacity(&ARMebHFTriples);
|
|
} else {
|
|
triple_aliases.appendSliceAssumeCapacity(&ARMebTriples);
|
|
}
|
|
},
|
|
.avr => {
|
|
lib_dirs.appendSliceAssumeCapacity(&AVRLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&AVRTriples);
|
|
},
|
|
.csky => {
|
|
lib_dirs.appendSliceAssumeCapacity(&CSKYLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&CSKYTriples);
|
|
},
|
|
.x86_64 => {
|
|
if (target.abi == .gnux32 or target.abi == .muslx32) {
|
|
lib_dirs.appendSliceAssumeCapacity(&X32LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&X32Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64Triples);
|
|
} else {
|
|
lib_dirs.appendSliceAssumeCapacity(&X86_64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&X86_64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X32LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X32Triples);
|
|
}
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X86LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X86Triples);
|
|
},
|
|
.x86 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&X86LibDirs);
|
|
// MCU toolchain is 32 bit only and its triple alias is TargetTriple
|
|
// itself, which will be appended below.
|
|
if (target.os.tag != .elfiamcu) {
|
|
triple_aliases.appendSliceAssumeCapacity(&X86Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&X32LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&X32Triples);
|
|
}
|
|
},
|
|
.loongarch64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&LoongArch64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&LoongArch64Triples);
|
|
},
|
|
.m68k => {
|
|
lib_dirs.appendSliceAssumeCapacity(&M68kLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&M68kTriples);
|
|
},
|
|
.mips => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPSLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPSTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPS64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32Triples);
|
|
},
|
|
.mipsel => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPSELLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPSELTriples);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPSTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64ELTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32ELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32ELTriples);
|
|
},
|
|
.mips64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPS64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPS64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32Triples);
|
|
},
|
|
.mips64el => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MIPS64ELTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSELTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32ELLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32ELTriples);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSTriples);
|
|
},
|
|
.msp430 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&MSP430LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&MSP430Triples);
|
|
},
|
|
.powerpc => {
|
|
lib_dirs.appendSliceAssumeCapacity(&PPCLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&PPCTriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&PPC64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&PPC64Triples);
|
|
},
|
|
.powerpcle => {
|
|
lib_dirs.appendSliceAssumeCapacity(&PPCLELibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&PPCLETriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&PPC64LELibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&PPC64LETriples);
|
|
},
|
|
.powerpc64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&PPC64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&PPC64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&PPCLibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&PPCTriples);
|
|
},
|
|
.powerpc64le => {
|
|
lib_dirs.appendSliceAssumeCapacity(&PPC64LELibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&PPC64LETriples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&PPCLELibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&PPCLETriples);
|
|
},
|
|
.riscv32 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&RISCV32LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&RISCV32Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&RISCV64LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&RISCV64Triples);
|
|
},
|
|
.riscv64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&RISCV64LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&RISCV64Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&RISCV32LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&RISCV32Triples);
|
|
},
|
|
.sparc => {
|
|
lib_dirs.appendSliceAssumeCapacity(&SPARCv8LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&SPARCv8Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&SPARCv9LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&SPARCv9Triples);
|
|
},
|
|
.sparc64 => {
|
|
lib_dirs.appendSliceAssumeCapacity(&SPARCv9LibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&SPARCv9Triples);
|
|
biarch_libdirs.appendSliceAssumeCapacity(&SPARCv8LibDirs);
|
|
biarch_triple_aliases.appendSliceAssumeCapacity(&SPARCv8Triples);
|
|
},
|
|
.s390x => {
|
|
lib_dirs.appendSliceAssumeCapacity(&SystemZLibDirs);
|
|
triple_aliases.appendSliceAssumeCapacity(&SystemZTriples);
|
|
},
|
|
else => {},
|
|
}
|
|
}
|
|
|
|
pub fn discover(self: *GCCDetector, tc: *Toolchain) !void {
|
|
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
|
var fib = std.heap.FixedBufferAllocator.init(&path_buf);
|
|
|
|
const target = tc.getTarget();
|
|
const biarch_variant_target = if (target.ptrBitWidth() == 32)
|
|
target_util.get64BitArchVariant(target)
|
|
else
|
|
target_util.get32BitArchVariant(target);
|
|
|
|
var candidate_lib_dirs_buffer: [16][]const u8 = undefined;
|
|
var candidate_lib_dirs = std.ArrayListUnmanaged([]const u8).initBuffer(&candidate_lib_dirs_buffer);
|
|
|
|
var candidate_triple_aliases_buffer: [16][]const u8 = undefined;
|
|
var candidate_triple_aliases = std.ArrayListUnmanaged([]const u8).initBuffer(&candidate_triple_aliases_buffer);
|
|
|
|
var candidate_biarch_lib_dirs_buffer: [16][]const u8 = undefined;
|
|
var candidate_biarch_lib_dirs = std.ArrayListUnmanaged([]const u8).initBuffer(&candidate_biarch_lib_dirs_buffer);
|
|
|
|
var candidate_biarch_triple_aliases_buffer: [16][]const u8 = undefined;
|
|
var candidate_biarch_triple_aliases = std.ArrayListUnmanaged([]const u8).initBuffer(&candidate_biarch_triple_aliases_buffer);
|
|
|
|
try collectLibDirsAndTriples(
|
|
tc,
|
|
&candidate_lib_dirs,
|
|
&candidate_triple_aliases,
|
|
&candidate_biarch_lib_dirs,
|
|
&candidate_biarch_triple_aliases,
|
|
);
|
|
|
|
var target_buf: [64]u8 = undefined;
|
|
const triple_str = target_util.toLLVMTriple(target, &target_buf);
|
|
candidate_triple_aliases.appendAssumeCapacity(triple_str);
|
|
|
|
// Also include the multiarch variant if it's different.
|
|
var biarch_buf: [64]u8 = undefined;
|
|
if (biarch_variant_target) |biarch_target| {
|
|
const biarch_triple_str = target_util.toLLVMTriple(biarch_target, &biarch_buf);
|
|
if (!std.mem.eql(u8, biarch_triple_str, triple_str)) {
|
|
candidate_triple_aliases.appendAssumeCapacity(biarch_triple_str);
|
|
}
|
|
}
|
|
|
|
var prefixes_buf: [16][]const u8 = undefined;
|
|
var prefixes = std.ArrayListUnmanaged([]const u8).initBuffer(&prefixes_buf);
|
|
const gcc_toolchain_dir = gccToolchainDir(tc);
|
|
if (gcc_toolchain_dir.len != 0) {
|
|
const adjusted = if (gcc_toolchain_dir[gcc_toolchain_dir.len - 1] == '/')
|
|
gcc_toolchain_dir[0 .. gcc_toolchain_dir.len - 1]
|
|
else
|
|
gcc_toolchain_dir;
|
|
prefixes.appendAssumeCapacity(adjusted);
|
|
} else {
|
|
const sysroot = tc.getSysroot();
|
|
if (sysroot.len > 0) {
|
|
prefixes.appendAssumeCapacity(sysroot);
|
|
try addDefaultGCCPrefixes(&prefixes, tc);
|
|
}
|
|
|
|
if (sysroot.len == 0) {
|
|
try addDefaultGCCPrefixes(&prefixes, tc);
|
|
}
|
|
// TODO: Special-case handling for Gentoo
|
|
}
|
|
|
|
const v0 = GCCVersion.parse("0.0.0");
|
|
for (prefixes.items) |prefix| {
|
|
if (!tc.filesystem.exists(prefix)) continue;
|
|
|
|
for (candidate_lib_dirs.items) |suffix| {
|
|
defer fib.reset();
|
|
const lib_dir = std.fs.path.join(fib.allocator(), &.{ prefix, suffix }) catch continue;
|
|
if (!tc.filesystem.exists(lib_dir)) continue;
|
|
|
|
const gcc_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc" });
|
|
const gcc_cross_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc-cross" });
|
|
|
|
try self.scanLibDirForGCCTriple(tc, target, lib_dir, triple_str, false, gcc_dir_exists, gcc_cross_dir_exists);
|
|
for (candidate_triple_aliases.items) |candidate| {
|
|
try self.scanLibDirForGCCTriple(tc, target, lib_dir, candidate, false, gcc_dir_exists, gcc_cross_dir_exists);
|
|
}
|
|
}
|
|
for (candidate_biarch_lib_dirs.items) |suffix| {
|
|
const lib_dir = std.fs.path.join(fib.allocator(), &.{ prefix, suffix }) catch continue;
|
|
if (!tc.filesystem.exists(lib_dir)) continue;
|
|
|
|
const gcc_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc" });
|
|
const gcc_cross_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc-cross" });
|
|
for (candidate_biarch_triple_aliases.items) |candidate| {
|
|
try self.scanLibDirForGCCTriple(tc, target, lib_dir, candidate, true, gcc_dir_exists, gcc_cross_dir_exists);
|
|
}
|
|
}
|
|
if (self.version.order(v0) == .gt) break;
|
|
}
|
|
}
|
|
|
|
fn findBiarchMultilibs(
|
|
tc: *const Toolchain,
|
|
result: *Multilib.Detected,
|
|
target: std.Target,
|
|
path: [2][]const u8,
|
|
needs_biarch_suffix: bool,
|
|
) !bool {
|
|
const suff64 = if (target.os.tag == .solaris) switch (target.cpu.arch) {
|
|
.x86, .x86_64 => "/amd64",
|
|
.sparc => "/sparcv9",
|
|
else => "/64",
|
|
} else "/64";
|
|
|
|
const alt_64 = Multilib.init(suff64, suff64, &.{ "-m32", "+m64", "-mx32" });
|
|
const alt_32 = Multilib.init("/32", "/32", &.{ "+m32", "-m64", "-mx32" });
|
|
const alt_x32 = Multilib.init("/x32", "/x32", &.{ "-m32", "-m64", "+mx32" });
|
|
|
|
const multilib_filter = Multilib.Filter{
|
|
.base = path,
|
|
.file = if (target.os.tag == .elfiamcu) "libgcc.a" else "crtbegin.o",
|
|
};
|
|
|
|
const Want = enum {
|
|
want32,
|
|
want64,
|
|
wantx32,
|
|
};
|
|
const is_x32 = target.abi == .gnux32 or target.abi == .muslx32;
|
|
const target_ptr_width = target.ptrBitWidth();
|
|
const want: Want = if (target_ptr_width == 32 and multilib_filter.exists(alt_32, tc.filesystem))
|
|
.want64
|
|
else if (target_ptr_width == 64 and is_x32 and multilib_filter.exists(alt_x32, tc.filesystem))
|
|
.want64
|
|
else if (target_ptr_width == 64 and !is_x32 and multilib_filter.exists(alt_64, tc.filesystem))
|
|
.want32
|
|
else if (target_ptr_width == 32)
|
|
if (needs_biarch_suffix) .want64 else .want32
|
|
else if (is_x32)
|
|
if (needs_biarch_suffix) .want64 else .wantx32
|
|
else if (needs_biarch_suffix) .want32 else .want64;
|
|
|
|
const default = switch (want) {
|
|
.want32 => Multilib.init("", "", &.{ "+m32", "-m64", "-mx32" }),
|
|
.want64 => Multilib.init("", "", &.{ "-m32", "+m64", "-mx32" }),
|
|
.wantx32 => Multilib.init("", "", &.{ "-m32", "-m64", "+mx32" }),
|
|
};
|
|
result.multilibs.appendSliceAssumeCapacity(&.{
|
|
default,
|
|
alt_64,
|
|
alt_32,
|
|
alt_x32,
|
|
});
|
|
result.filter(multilib_filter, tc.filesystem);
|
|
var flags: Multilib.Flags = .{};
|
|
flags.appendAssumeCapacity(if (target_ptr_width == 64 and !is_x32) "+m64" else "-m64");
|
|
flags.appendAssumeCapacity(if (target_ptr_width == 32) "+m32" else "-m32");
|
|
flags.appendAssumeCapacity(if (target_ptr_width == 64 and is_x32) "+mx32" else "-mx32");
|
|
|
|
return result.select(flags);
|
|
}
|
|
|
|
fn scanGCCForMultilibs(
|
|
self: *GCCDetector,
|
|
tc: *const Toolchain,
|
|
target: std.Target,
|
|
path: [2][]const u8,
|
|
needs_biarch_suffix: bool,
|
|
) !bool {
|
|
var detected: Multilib.Detected = .{};
|
|
if (target.cpu.arch == .csky) {
|
|
// TODO
|
|
} else if (target.cpu.arch.isMIPS()) {
|
|
// TODO
|
|
} else if (target.cpu.arch.isRISCV()) {
|
|
// TODO
|
|
} else if (target.cpu.arch == .msp430) {
|
|
// TODO
|
|
} else if (target.cpu.arch == .avr) {
|
|
// No multilibs
|
|
} else if (!try findBiarchMultilibs(tc, &detected, target, path, needs_biarch_suffix)) {
|
|
return false;
|
|
}
|
|
self.selected = detected.selected;
|
|
self.biarch_sibling = detected.biarch_sibling;
|
|
return true;
|
|
}
|
|
|
|
fn scanLibDirForGCCTriple(
|
|
self: *GCCDetector,
|
|
tc: *const Toolchain,
|
|
target: std.Target,
|
|
lib_dir: []const u8,
|
|
candidate_triple: []const u8,
|
|
needs_biarch_suffix: bool,
|
|
gcc_dir_exists: bool,
|
|
gcc_cross_dir_exists: bool,
|
|
) !void {
|
|
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
|
var fib = std.heap.FixedBufferAllocator.init(&path_buf);
|
|
for (0..2) |i| {
|
|
if (i == 0 and !gcc_dir_exists) continue;
|
|
if (i == 1 and !gcc_cross_dir_exists) continue;
|
|
defer fib.reset();
|
|
|
|
const base: []const u8 = if (i == 0) "gcc" else "gcc-cross";
|
|
var lib_suffix_buf: [64]u8 = undefined;
|
|
var suffix_buf_fib = std.heap.FixedBufferAllocator.init(&lib_suffix_buf);
|
|
const lib_suffix = std.fs.path.join(suffix_buf_fib.allocator(), &.{ base, candidate_triple }) catch continue;
|
|
|
|
const dir_name = std.fs.path.join(fib.allocator(), &.{ lib_dir, lib_suffix }) catch continue;
|
|
var parent_dir = tc.filesystem.openDir(dir_name) catch continue;
|
|
defer parent_dir.close();
|
|
|
|
var it = parent_dir.iterate();
|
|
while (it.next() catch continue) |entry| {
|
|
if (entry.kind != .directory) continue;
|
|
|
|
const version_text = entry.name;
|
|
const candidate_version = GCCVersion.parse(version_text);
|
|
if (candidate_version.major != -1) {
|
|
// TODO: cache path so we're not repeatedly scanning
|
|
}
|
|
if (candidate_version.isLessThan(4, 1, 1, "")) continue;
|
|
switch (candidate_version.order(self.version)) {
|
|
.lt, .eq => continue,
|
|
.gt => {},
|
|
}
|
|
|
|
if (!try self.scanGCCForMultilibs(tc, target, .{ dir_name, version_text }, needs_biarch_suffix)) continue;
|
|
|
|
self.version = candidate_version;
|
|
self.gcc_triple = try tc.arena.dupe(u8, candidate_triple);
|
|
self.install_path = try std.fs.path.join(tc.arena, &.{ lib_dir, lib_suffix, version_text });
|
|
self.parent_lib_path = try std.fs.path.join(tc.arena, &.{ self.install_path, "..", "..", ".." });
|
|
self.is_valid = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn gccToolchainDir(tc: *const Toolchain) []const u8 {
|
|
const sysroot = tc.getSysroot();
|
|
if (sysroot.len != 0) return "";
|
|
return system_defaults.gcc_install_prefix;
|
|
}
|