mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
277 lines
9.6 KiB
Zig
277 lines
9.6 KiB
Zig
libc_include_dir_list: []const []const u8,
|
|
libc_installation: ?*const LibCInstallation,
|
|
libc_framework_dir_list: []const []const u8,
|
|
sysroot: ?[]const u8,
|
|
darwin_sdk_layout: ?DarwinSdkLayout,
|
|
|
|
/// The filesystem layout of darwin SDK elements.
|
|
pub const DarwinSdkLayout = enum {
|
|
/// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }.
|
|
sdk,
|
|
/// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, <NONE> }.
|
|
vendored,
|
|
};
|
|
|
|
pub fn detect(
|
|
arena: Allocator,
|
|
zig_lib_dir: []const u8,
|
|
target: *const std.Target,
|
|
is_native_abi: bool,
|
|
link_libc: bool,
|
|
libc_installation: ?*const LibCInstallation,
|
|
) LibCInstallation.FindError!LibCDirs {
|
|
if (!link_libc) {
|
|
return .{
|
|
.libc_include_dir_list = &[0][]u8{},
|
|
.libc_installation = null,
|
|
.libc_framework_dir_list = &.{},
|
|
.sysroot = null,
|
|
.darwin_sdk_layout = null,
|
|
};
|
|
}
|
|
|
|
if (libc_installation) |lci| {
|
|
return detectFromInstallation(arena, target, lci);
|
|
}
|
|
|
|
// If linking system libraries and targeting the native abi, default to
|
|
// using the system libc installation.
|
|
if (is_native_abi and !target.isMinGW()) {
|
|
const libc = try arena.create(LibCInstallation);
|
|
libc.* = LibCInstallation.findNative(.{ .allocator = arena, .target = target }) catch |err| switch (err) {
|
|
error.CCompilerExitCode,
|
|
error.CCompilerCrashed,
|
|
error.CCompilerCannotFindHeaders,
|
|
error.UnableToSpawnCCompiler,
|
|
error.DarwinSdkNotFound,
|
|
=> |e| {
|
|
// We tried to integrate with the native system C compiler,
|
|
// however, it is not installed. So we must rely on our bundled
|
|
// libc files.
|
|
if (std.zig.target.canBuildLibC(target)) {
|
|
return detectFromBuilding(arena, zig_lib_dir, target);
|
|
}
|
|
return e;
|
|
},
|
|
else => |e| return e,
|
|
};
|
|
return detectFromInstallation(arena, target, libc);
|
|
}
|
|
|
|
// If not linking system libraries, build and provide our own libc by
|
|
// default if possible.
|
|
if (std.zig.target.canBuildLibC(target)) {
|
|
return detectFromBuilding(arena, zig_lib_dir, target);
|
|
}
|
|
|
|
// If zig can't build the libc for the target and we are targeting the
|
|
// native abi, fall back to using the system libc installation.
|
|
// On windows, instead of the native (mingw) abi, we want to check
|
|
// for the MSVC abi as a fallback.
|
|
const use_system_abi = if (builtin.os.tag == .windows)
|
|
target.abi == .msvc or target.abi == .itanium
|
|
else
|
|
is_native_abi;
|
|
|
|
if (use_system_abi) {
|
|
const libc = try arena.create(LibCInstallation);
|
|
libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, .target = target });
|
|
return detectFromInstallation(arena, target, libc);
|
|
}
|
|
|
|
return .{
|
|
.libc_include_dir_list = &[0][]u8{},
|
|
.libc_installation = null,
|
|
.libc_framework_dir_list = &.{},
|
|
.sysroot = null,
|
|
.darwin_sdk_layout = null,
|
|
};
|
|
}
|
|
|
|
fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *const LibCInstallation) !LibCDirs {
|
|
var list = try std.array_list.Managed([]const u8).initCapacity(arena, 5);
|
|
var framework_list = std.array_list.Managed([]const u8).init(arena);
|
|
|
|
list.appendAssumeCapacity(lci.include_dir.?);
|
|
|
|
const is_redundant = std.mem.eql(u8, lci.sys_include_dir.?, lci.include_dir.?);
|
|
if (!is_redundant) list.appendAssumeCapacity(lci.sys_include_dir.?);
|
|
|
|
if (target.os.tag == .windows) {
|
|
if (std.fs.path.dirname(lci.sys_include_dir.?)) |sys_include_dir_parent| {
|
|
// This include path will only exist when the optional "Desktop development with C++"
|
|
// is installed. It contains headers, .rc files, and resources. It is especially
|
|
// necessary when working with Windows resources.
|
|
const atlmfc_dir = try std.fs.path.join(arena, &[_][]const u8{ sys_include_dir_parent, "atlmfc", "include" });
|
|
list.appendAssumeCapacity(atlmfc_dir);
|
|
}
|
|
if (std.fs.path.dirname(lci.include_dir.?)) |include_dir_parent| {
|
|
const um_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_parent, "um" });
|
|
list.appendAssumeCapacity(um_dir);
|
|
|
|
const shared_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_parent, "shared" });
|
|
list.appendAssumeCapacity(shared_dir);
|
|
}
|
|
}
|
|
if (target.os.tag == .haiku) {
|
|
const include_dir_path = lci.include_dir.?;
|
|
const os_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_path, "os" });
|
|
list.appendAssumeCapacity(os_dir);
|
|
// Errors.h
|
|
const os_support_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_path, "os/support" });
|
|
list.appendAssumeCapacity(os_support_dir);
|
|
|
|
const config_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_path, "config" });
|
|
list.appendAssumeCapacity(config_dir);
|
|
}
|
|
|
|
var sysroot: ?[]const u8 = null;
|
|
|
|
if (target.os.tag.isDarwin()) d: {
|
|
const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d;
|
|
const down2 = std.fs.path.dirname(down1) orelse break :d;
|
|
try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" }));
|
|
sysroot = down2;
|
|
}
|
|
|
|
return .{
|
|
.libc_include_dir_list = list.items,
|
|
.libc_installation = lci,
|
|
.libc_framework_dir_list = framework_list.items,
|
|
.sysroot = sysroot,
|
|
.darwin_sdk_layout = if (sysroot == null) null else .sdk,
|
|
};
|
|
}
|
|
|
|
pub fn detectFromBuilding(
|
|
arena: Allocator,
|
|
zig_lib_dir: []const u8,
|
|
target: *const std.Target,
|
|
) !LibCDirs {
|
|
const s = std.fs.path.sep_str;
|
|
|
|
if (target.os.tag.isDarwin()) {
|
|
const list = try arena.alloc([]const u8, 1);
|
|
list[0] = try std.fmt.allocPrint(
|
|
arena,
|
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any",
|
|
.{zig_lib_dir},
|
|
);
|
|
return .{
|
|
.libc_include_dir_list = list,
|
|
.libc_installation = null,
|
|
.libc_framework_dir_list = &.{},
|
|
.sysroot = null,
|
|
.darwin_sdk_layout = .vendored,
|
|
};
|
|
}
|
|
|
|
const generic_name = libCGenericName(target);
|
|
// Some architecture families are handled by the same set of headers.
|
|
const arch_name = if (target.isMuslLibC() or target.isWasiLibC())
|
|
std.zig.target.muslArchNameHeaders(target.cpu.arch)
|
|
else if (target.isGnuLibC())
|
|
std.zig.target.glibcArchNameHeaders(target.cpu.arch)
|
|
else if (target.isFreeBSDLibC())
|
|
std.zig.target.freebsdArchNameHeaders(target.cpu.arch)
|
|
else if (target.isNetBSDLibC())
|
|
std.zig.target.netbsdArchNameHeaders(target.cpu.arch)
|
|
else
|
|
@tagName(target.cpu.arch);
|
|
const os_name = @tagName(target.os.tag);
|
|
const abi_name = if (target.isMuslLibC())
|
|
std.zig.target.muslAbiNameHeaders(target.abi)
|
|
else if (target.isGnuLibC())
|
|
std.zig.target.glibcAbiNameHeaders(target.abi)
|
|
else if (target.isNetBSDLibC())
|
|
std.zig.target.netbsdAbiNameHeaders(target.abi)
|
|
else
|
|
@tagName(target.abi);
|
|
const arch_include_dir = try std.fmt.allocPrint(
|
|
arena,
|
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
|
|
.{ zig_lib_dir, arch_name, os_name, abi_name },
|
|
);
|
|
const generic_include_dir = try std.fmt.allocPrint(
|
|
arena,
|
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
|
|
.{ zig_lib_dir, generic_name },
|
|
);
|
|
const generic_arch_name = std.zig.target.osArchName(target);
|
|
const arch_os_include_dir = try std.fmt.allocPrint(
|
|
arena,
|
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
|
|
.{ zig_lib_dir, generic_arch_name, os_name },
|
|
);
|
|
const generic_os_include_dir = try std.fmt.allocPrint(
|
|
arena,
|
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
|
|
.{ zig_lib_dir, os_name },
|
|
);
|
|
|
|
const list = try arena.alloc([]const u8, 4);
|
|
list[0] = arch_include_dir;
|
|
list[1] = generic_include_dir;
|
|
list[2] = arch_os_include_dir;
|
|
list[3] = generic_os_include_dir;
|
|
|
|
return .{
|
|
.libc_include_dir_list = list,
|
|
.libc_installation = null,
|
|
.libc_framework_dir_list = &.{},
|
|
.sysroot = null,
|
|
.darwin_sdk_layout = .vendored,
|
|
};
|
|
}
|
|
|
|
fn libCGenericName(target: *const std.Target) [:0]const u8 {
|
|
switch (target.os.tag) {
|
|
.windows => return "mingw",
|
|
.macos, .ios, .tvos, .watchos, .visionos => return "darwin",
|
|
.freebsd => return "freebsd",
|
|
.netbsd => return "netbsd",
|
|
else => {},
|
|
}
|
|
switch (target.abi) {
|
|
.gnu,
|
|
.gnuabin32,
|
|
.gnuabi64,
|
|
.gnueabi,
|
|
.gnueabihf,
|
|
.gnuf32,
|
|
.gnusf,
|
|
.gnux32,
|
|
=> return "glibc",
|
|
.musl,
|
|
.muslabin32,
|
|
.muslabi64,
|
|
.musleabi,
|
|
.musleabihf,
|
|
.muslf32,
|
|
.muslsf,
|
|
.muslx32,
|
|
.none,
|
|
.ohos,
|
|
.ohoseabi,
|
|
=> return "musl",
|
|
.code16,
|
|
.eabi,
|
|
.eabihf,
|
|
.ilp32,
|
|
.android,
|
|
.androideabi,
|
|
.msvc,
|
|
.itanium,
|
|
.cygnus,
|
|
.simulator,
|
|
.macabi,
|
|
=> unreachable,
|
|
}
|
|
}
|
|
|
|
const LibCDirs = @This();
|
|
const builtin = @import("builtin");
|
|
const std = @import("../std.zig");
|
|
const LibCInstallation = std.zig.LibCInstallation;
|
|
const Allocator = std.mem.Allocator;
|