diff --git a/pkg/apple-sdk/build.zig b/pkg/apple-sdk/build.zig index 1be733dd6..18a6c0968 100644 --- a/pkg/apple-sdk/build.zig +++ b/pkg/apple-sdk/build.zig @@ -7,12 +7,17 @@ pub fn build(b: *std.Build) !void { _ = optimize; } -/// Add the SDK framework, include, and library paths to the given module. -/// The module target is used to determine the SDK to use so it must have -/// a resolved target. -pub fn addPaths(b: *std.Build, m: *std.Build.Module) !void { +/// Setup the step to point to the proper Apple SDK for libc and +/// frameworks. This expects and relies on the native SDK being +/// installed on the system. Ghostty doesn't support cross-compilation +/// for Apple platforms. +pub fn addPaths( + b: *std.Build, + step: *std.Build.Step.Compile, +) !void { // The cache. This always uses b.allocator and never frees memory - // (which is idiomatic for a Zig build exe). + // (which is idiomatic for a Zig build exe). We cache the libc txt + // file we create because it is expensive to generate (subprocesses). const Cache = struct { const Key = struct { arch: std.Target.Cpu.Arch, @@ -20,27 +25,72 @@ pub fn addPaths(b: *std.Build, m: *std.Build.Module) !void { abi: std.Target.Abi, }; - var map: std.AutoHashMapUnmanaged(Key, ?[]const u8) = .{}; + var map: std.AutoHashMapUnmanaged(Key, ?struct { + libc: std.Build.LazyPath, + framework: []const u8, + system_include: []const u8, + library: []const u8, + }) = .{}; }; - const target = m.resolved_target.?.result; + const target = step.rootModuleTarget(); const gop = try Cache.map.getOrPut(b.allocator, .{ .arch = target.cpu.arch, .os = target.os.tag, .abi = target.abi, }); - // This executes `xcrun` to get the SDK path. We don't want to execute - // this multiple times so we cache the value. if (!gop.found_existing) { - gop.value_ptr.* = std.zig.system.darwin.getSdk( - b.allocator, - m.resolved_target.?.result, - ); + // 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 = try std.zig.LibCInstallation.findNative(.{ + .allocator = b.allocator, + .target = step.rootModuleTarget(), + .verbose = false, + }); + + // Render the file compatible with the `--libc` Zig flag. + var list: std.ArrayList(u8) = .init(b.allocator); + defer list.deinit(); + try libc.render(list.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", list.items); + + // 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.* = .{ + .libc = path, + .framework = framework_path, + .system_include = libc.sys_include_dir.?, + .library = library_path, + }; } - // The active SDK we want to use - const path = gop.value_ptr.* orelse return switch (target.os.tag) { + const value = 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. @@ -50,7 +100,12 @@ pub fn addPaths(b: *std.Build, m: *std.Build.Module) !void { .watchos => error.XcodeWatchOSSDKNotFound, else => error.XcodeAppleSDKNotFound, }; - m.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ path, "/System/Library/Frameworks" }) }); - m.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ path, "/usr/include" }) }); - m.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ path, "/usr/lib" }) }); + + step.setLibCFile(value.libc); + + // This is only necessary until this bug is fixed: + // https://github.com/ziglang/zig/issues/24024 + step.root_module.addSystemFrameworkPath(.{ .cwd_relative = value.framework }); + step.root_module.addSystemIncludePath(.{ .cwd_relative = value.system_include }); + step.root_module.addLibraryPath(.{ .cwd_relative = value.library }); } diff --git a/pkg/breakpad/build.zig b/pkg/breakpad/build.zig index e2fdec7ad..42247b12c 100644 --- a/pkg/breakpad/build.zig +++ b/pkg/breakpad/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) !void { lib.addIncludePath(b.path("vendor")); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/cimgui/build.zig b/pkg/cimgui/build.zig index c76b53966..3ca735383 100644 --- a/pkg/cimgui/build.zig +++ b/pkg/cimgui/build.zig @@ -84,8 +84,7 @@ pub fn build(b: *std.Build) !void { if (target.result.os.tag.isDarwin()) { if (!target.query.isNative()) { - try @import("apple_sdk").addPaths(b, lib.root_module); - try @import("apple_sdk").addPaths(b, module); + try @import("apple_sdk").addPaths(b, lib); } lib.addCSourceFile(.{ .file = imgui.path("backends/imgui_impl_metal.mm"), diff --git a/pkg/freetype/build.zig b/pkg/freetype/build.zig index bfe27e5aa..e9f72210a 100644 --- a/pkg/freetype/build.zig +++ b/pkg/freetype/build.zig @@ -69,7 +69,7 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu lib.linkLibC(); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/glfw/build.zig b/pkg/glfw/build.zig index cc61f18b2..142a558da 100644 --- a/pkg/glfw/build.zig +++ b/pkg/glfw/build.zig @@ -24,7 +24,7 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); if (target.result.os.tag.isDarwin()) { - try apple_sdk.addPaths(b, exe.root_module); + try apple_sdk.addPaths(b, exe); } const tests_run = b.addRunArtifact(exe); @@ -122,8 +122,7 @@ fn buildLib( }, .macos => { - try apple_sdk.addPaths(b, lib.root_module); - try apple_sdk.addPaths(b, module); + try apple_sdk.addPaths(b, lib); // Transitive dependencies, explicit linkage of these works around // ziglang/zig#17130 diff --git a/pkg/glslang/build.zig b/pkg/glslang/build.zig index 629490aa4..747216a39 100644 --- a/pkg/glslang/build.zig +++ b/pkg/glslang/build.zig @@ -16,10 +16,6 @@ pub fn build(b: *std.Build) !void { module.addIncludePath(upstream.path("")); module.addIncludePath(b.path("override")); - if (target.result.os.tag.isDarwin()) { - const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, module); - } if (target.query.isNative()) { const test_exe = b.addTest(.{ @@ -55,7 +51,7 @@ fn buildGlslang( lib.addIncludePath(b.path("override")); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/harfbuzz/build.zig b/pkg/harfbuzz/build.zig index d0dd6d01c..3bdc30a32 100644 --- a/pkg/harfbuzz/build.zig +++ b/pkg/harfbuzz/build.zig @@ -93,8 +93,7 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu lib.linkLibCpp(); if (target.result.os.tag.isDarwin()) { - try apple_sdk.addPaths(b, lib.root_module); - try apple_sdk.addPaths(b, module); + try apple_sdk.addPaths(b, lib); } const dynamic_link_opts = options.dynamic_link_opts; diff --git a/pkg/highway/build.zig b/pkg/highway/build.zig index c72ca355f..5036316da 100644 --- a/pkg/highway/build.zig +++ b/pkg/highway/build.zig @@ -23,8 +23,7 @@ pub fn build(b: *std.Build) !void { if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); - try apple_sdk.addPaths(b, module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/libintl/build.zig b/pkg/libintl/build.zig index 53eb67f16..1baed195a 100644 --- a/pkg/libintl/build.zig +++ b/pkg/libintl/build.zig @@ -40,7 +40,7 @@ pub fn build(b: *std.Build) !void { if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } if (b.lazyDependency("gettext", .{})) |upstream| { diff --git a/pkg/libpng/build.zig b/pkg/libpng/build.zig index d012f2712..8729398f8 100644 --- a/pkg/libpng/build.zig +++ b/pkg/libpng/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) !void { } if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } // For dynamic linking, we prefer dynamic linking and to search by diff --git a/pkg/macos/build.zig b/pkg/macos/build.zig index 911664a2f..df76da9b4 100644 --- a/pkg/macos/build.zig +++ b/pkg/macos/build.zig @@ -45,8 +45,7 @@ pub fn build(b: *std.Build) !void { module.linkFramework("CoreVideo", .{}); module.linkFramework("QuartzCore", .{}); - try apple_sdk.addPaths(b, lib.root_module); - try apple_sdk.addPaths(b, module); + try apple_sdk.addPaths(b, lib); } b.installArtifact(lib); @@ -58,7 +57,7 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }); if (target.result.os.tag.isDarwin()) { - try apple_sdk.addPaths(b, test_exe.root_module); + try apple_sdk.addPaths(b, test_exe); } test_exe.linkLibrary(lib); diff --git a/pkg/oniguruma/build.zig b/pkg/oniguruma/build.zig index 1c93bbf9a..c23d744df 100644 --- a/pkg/oniguruma/build.zig +++ b/pkg/oniguruma/build.zig @@ -67,7 +67,7 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } if (b.lazyDependency("oniguruma", .{})) |upstream| { diff --git a/pkg/sentry/build.zig b/pkg/sentry/build.zig index 3c0019710..0e6993ad4 100644 --- a/pkg/sentry/build.zig +++ b/pkg/sentry/build.zig @@ -20,8 +20,7 @@ pub fn build(b: *std.Build) !void { lib.linkLibC(); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); - try apple_sdk.addPaths(b, module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/simdutf/build.zig b/pkg/simdutf/build.zig index 859653443..30de40fea 100644 --- a/pkg/simdutf/build.zig +++ b/pkg/simdutf/build.zig @@ -14,7 +14,7 @@ pub fn build(b: *std.Build) !void { if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/spirv-cross/build.zig b/pkg/spirv-cross/build.zig index c7d0d2039..ff67e3e72 100644 --- a/pkg/spirv-cross/build.zig +++ b/pkg/spirv-cross/build.zig @@ -44,7 +44,7 @@ fn buildSpirvCross( lib.linkLibCpp(); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/utfcpp/build.zig b/pkg/utfcpp/build.zig index 6b80fec7b..8e1a3cb20 100644 --- a/pkg/utfcpp/build.zig +++ b/pkg/utfcpp/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) !void { if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } var flags = std.ArrayList([]const u8).init(b.allocator); diff --git a/pkg/wuffs/build.zig b/pkg/wuffs/build.zig index d47771c22..4d144e76a 100644 --- a/pkg/wuffs/build.zig +++ b/pkg/wuffs/build.zig @@ -11,11 +11,6 @@ pub fn build(b: *std.Build) !void { .link_libc = true, }); - if (target.result.os.tag.isDarwin()) { - const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, module); - } - const unit_tests = b.addTest(.{ .root_source_file = b.path("src/main.zig"), .target = target, diff --git a/pkg/zlib/build.zig b/pkg/zlib/build.zig index 28ae62424..28344c989 100644 --- a/pkg/zlib/build.zig +++ b/pkg/zlib/build.zig @@ -12,7 +12,7 @@ pub fn build(b: *std.Build) !void { lib.linkLibC(); if (target.result.os.tag.isDarwin()) { const apple_sdk = @import("apple_sdk"); - try apple_sdk.addPaths(b, lib.root_module); + try apple_sdk.addPaths(b, lib); } if (b.lazyDependency("zlib", .{})) |upstream| { diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 512975ac0..d3741a358 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -377,7 +377,7 @@ pub fn add( // We always require the system SDK so that our system headers are available. // This makes things like `os/log.h` available for cross-compiling. if (step.rootModuleTarget().os.tag.isDarwin()) { - try @import("apple_sdk").addPaths(b, step.root_module); + try @import("apple_sdk").addPaths(b, step); const metallib = self.metallib.?; metallib.output.addStepDependencies(&step.step);