Files
ghostty/pkg/apple-sdk/build.zig
Chris Marchesi e8525c0fd9 Update to Zig 0.16.0
This commit represents the majority of the work necessary to upgrade
Ghostty to use Zig 0.16.0.

Key parts:

* In addition to its previous responsibilities, the global state now
  houses state for global I/O implementations and the process
  environment. It is now also utilized in the main application along
  with the C library. Where necessary, global state is isolated from key
  parts of the implementation (e.g., in libghostty subsystems), and it's
  expected that this list will grow.

* We currently manage our own C translation layer where necessary. In
  these cases, cImport has been removed in favor of the new external
  translate-c package. Due to fixes that have needed be made to properly
  translate the dependencies that were swapped out, as mentioned, we
  have had to backport fixes from the current translate-c package (and
  the upstream Arocc dependency). We will host this ourselves until Zig
  0.17.0 is released with these fixes.

* Where necessary (only a small number of cases), some stdlib code from
  0.15.2 (and even from 0.17.0) has been taken, adopted, and vendored in
  lib/compat.

Co-authored-by: Leah Amelia Chen <hi@pluie.me>
2026-07-21 12:35:05 -07:00

168 lines
6.0 KiB
Zig

const std = @import("std");
const builtin = @import("builtin");
// The cache. This always uses b.allocator and never frees memory
// (which is idiomatic for a Zig build exe). We cache the libc txt
// file we create because it is expensive to generate (subprocesses).
pub const Cache = struct {
const Key = struct {
arch: std.Target.Cpu.Arch,
os: std.Target.Os.Tag,
abi: std.Target.Abi,
};
pub const Value = union(enum) {
native: struct {
libc: std.Build.LazyPath,
framework: []const u8,
system_include: []const u8,
library: []const u8,
},
cross: struct {
libc: std.Build.LazyPath,
},
};
var map: std.AutoHashMapUnmanaged(Key, ?Value) = .{};
};
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
_ = target;
_ = optimize;
}
/// Fetch or load the paths for the proper Apple SDK for libc and
/// frameworks. When running on a Darwin host, this uses the native
/// SDK installed on the system via `xcrun`. When cross-compiling from
/// a non-Darwin host, it falls back to Zig's bundled Darwin headers.
pub fn pathsForTarget(b: *std.Build, target: std.Target) !Cache.Value {
const gop = try Cache.map.getOrPut(b.allocator, .{
.arch = target.cpu.arch,
.os = target.os.tag,
.abi = target.abi,
});
if (!gop.found_existing) init: {
if (comptime builtin.os.tag.isDarwin()) darwin: {
// Detect our SDK using the "findNative" Zig stdlib function.
// This is really important because it forces using `xcrun` to
// find the SDK path.
const libc = std.zig.LibCInstallation.findNative(
b.allocator,
b.graph.io,
.{
.environ_map = &b.graph.environ_map,
.target = &target,
.verbose = false,
},
) catch break :darwin;
// Render the file compatible with the `--libc` Zig flag.
var stream: std.Io.Writer.Allocating = .init(b.allocator);
defer stream.deinit();
try libc.render(&stream.writer);
// Create a temporary file to store the libc path because
// `--libc` expects a file path.
const wf = b.addWriteFiles();
const path = wf.add("libc.txt", stream.written());
// Determine our framework path. Zig has a bug where it doesn't
// parse this from the libc txt file for `-framework` flags:
// https://github.com/ziglang/zig/issues/24024
const framework_path = framework: {
const down1 = std.fs.path.dirname(libc.sys_include_dir.?).?;
const down2 = std.fs.path.dirname(down1).?;
break :framework try std.fs.path.join(b.allocator, &.{
down2,
"System",
"Library",
"Frameworks",
});
};
const library_path = library: {
const down1 = std.fs.path.dirname(libc.sys_include_dir.?).?;
break :library try std.fs.path.join(b.allocator, &.{
down1,
"lib",
});
};
gop.value_ptr.* = .{ .native = .{
.libc = path,
.framework = framework_path,
.system_include = libc.sys_include_dir.?,
.library = library_path,
} };
break :init;
}
// Cross-compiling to Darwin from a non-Darwin host.
// Zig only bundles macOS headers, so for other Apple platforms
// we leave the value as null to produce a descriptive error.
if (target.os.tag != .macos) {
gop.value_ptr.* = null;
break :init;
}
// Fall back to Zig's bundled Darwin headers for libc resolution.
const zig_lib_path = b.graph.zig_lib_directory.path.?;
const include_dir = b.pathJoin(&.{
zig_lib_path, "libc", "include", "any-darwin-any",
});
const wf = b.addWriteFiles();
const path = wf.add("libc.txt", b.fmt(
\\include_dir={s}
\\sys_include_dir={s}
\\crt_dir=
\\msvc_lib_dir=
\\kernel32_lib_dir=
\\gcc_dir=
\\
, .{ include_dir, include_dir }));
gop.value_ptr.* = .{ .cross = .{ .libc = path } };
}
return gop.value_ptr.* orelse return switch (target.os.tag) {
// Return a more descriptive error. Before we just returned the
// generic error but this was confusing a lot of community members.
// It costs us nothing in the build script to return something better.
.macos => error.XcodeMacOSSDKNotFound,
.ios => error.XcodeiOSSDKNotFound,
.tvos => error.XcodeTVOSSDKNotFound,
.watchos => error.XcodeWatchOSSDKNotFound,
else => error.XcodeAppleSDKNotFound,
};
}
/// Setup the step to point to the proper Apple SDK for libc and
/// frameworks. When running on a Darwin host, this uses the native
/// SDK installed on the system via `xcrun`. When cross-compiling from
/// a non-Darwin host, it falls back to Zig's bundled Darwin headers.
pub fn addPaths(
b: *std.Build,
step: *std.Build.Step.Compile,
) !void {
const target = step.rootModuleTarget();
switch (try pathsForTarget(b, target)) {
.native => |native| {
step.setLibCFile(native.libc);
// This is only necessary until this bug is fixed:
// https://github.com/ziglang/zig/issues/24024
step.root_module.addSystemFrameworkPath(.{ .cwd_relative = native.framework });
step.root_module.addSystemIncludePath(.{ .cwd_relative = native.system_include });
step.root_module.addLibraryPath(.{ .cwd_relative = native.library });
},
.cross => |cross| {
step.setLibCFile(cross.libc);
},
}
}