libghostty: enable cross-compiling macOS from Linux/Windows
This allows libghostty-vt to be cross-compiled for macOS from non-macOS platforms. I've updated pkg/apple-sdk to fallback to Zig's embedded macOS headers if the macOS SDK is not found. Additionally, CombineArchivesStep has been updated to use Linux tooling on Linux.pull/12417/head
parent
48ccec182a
commit
6b69ea0517
|
|
@ -569,14 +569,15 @@ jobs:
|
|||
build-libghostty-vt:
|
||||
strategy:
|
||||
matrix:
|
||||
target:
|
||||
[
|
||||
target: [
|
||||
aarch64-macos,
|
||||
x86_64-macos,
|
||||
aarch64-linux,
|
||||
x86_64-linux,
|
||||
x86_64-linux-musl,
|
||||
x86_64-windows,
|
||||
x86_64-windows-gnu,
|
||||
# doesn't work yet, we need a way to find msvc libc/c++ headers
|
||||
# x86_64-windows-msvc
|
||||
wasm32-freestanding,
|
||||
]
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
|
|
@ -607,8 +608,7 @@ jobs:
|
|||
- name: Build
|
||||
run: |
|
||||
nix develop -c zig build -Demit-lib-vt \
|
||||
-Dtarget=${{ matrix.target }} \
|
||||
-Dsimd=false
|
||||
-Dtarget=${{ matrix.target }}
|
||||
|
||||
# lib-vt requires macOS runner for macOS/iOS builds because it requires the `apple_sdk` path
|
||||
build-libghostty-vt-macos:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
|
@ -8,9 +9,9 @@ pub fn build(b: *std.Build) !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.
|
||||
/// 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,
|
||||
|
|
@ -25,12 +26,19 @@ pub fn addPaths(
|
|||
abi: std.Target.Abi,
|
||||
};
|
||||
|
||||
var map: std.AutoHashMapUnmanaged(Key, ?struct {
|
||||
libc: std.Build.LazyPath,
|
||||
framework: []const u8,
|
||||
system_include: []const u8,
|
||||
library: []const u8,
|
||||
}) = .{};
|
||||
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) = .{};
|
||||
};
|
||||
|
||||
const target = step.rootModuleTarget();
|
||||
|
|
@ -40,54 +48,85 @@ pub fn addPaths(
|
|||
.abi = target.abi,
|
||||
});
|
||||
|
||||
if (!gop.found_existing) {
|
||||
// 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,
|
||||
if (!gop.found_existing) init: {
|
||||
if (comptime builtin.os.tag.isDarwin()) {
|
||||
// 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 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-macos-any",
|
||||
});
|
||||
|
||||
// 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());
|
||||
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 }));
|
||||
|
||||
// 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,
|
||||
};
|
||||
gop.value_ptr.* = .{ .cross = .{ .libc = path } };
|
||||
}
|
||||
|
||||
const value = gop.value_ptr.* orelse return switch (target.os.tag) {
|
||||
|
|
@ -101,11 +140,18 @@ pub fn addPaths(
|
|||
else => error.XcodeAppleSDKNotFound,
|
||||
};
|
||||
|
||||
step.setLibCFile(value.libc);
|
||||
switch (value) {
|
||||
.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 = value.framework });
|
||||
step.root_module.addSystemIncludePath(.{ .cwd_relative = value.system_include });
|
||||
step.root_module.addLibraryPath(.{ .cwd_relative = value.library });
|
||||
// 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);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,8 +83,9 @@ pub fn build(b: *std.Build) !void {
|
|||
"-fno-sanitize-trap=undefined",
|
||||
});
|
||||
|
||||
if (target.result.os.tag == .freebsd or target.result.abi == .musl) {
|
||||
if (target.result.os.tag == .freebsd or target.result.os.tag == .linux) {
|
||||
try flags.append(b.allocator, "-fPIC");
|
||||
lib.root_module.pic = true;
|
||||
}
|
||||
|
||||
if (target.result.os.tag != .windows) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
//! Uses libtool on Darwin and a cross-platform MRI-script build tool
|
||||
//! on all other platforms (including Windows).
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const LibtoolStep = @import("LibtoolStep.zig");
|
||||
|
||||
/// Combine multiple static archives into a single fat archive.
|
||||
|
|
@ -15,7 +16,9 @@ pub fn create(
|
|||
name: []const u8,
|
||||
sources: []const std.Build.LazyPath,
|
||||
) struct { step: *std.Build.Step, output: std.Build.LazyPath } {
|
||||
if (target.result.os.tag.isDarwin()) {
|
||||
if (target.result.os.tag.isDarwin() and
|
||||
comptime builtin.os.tag.isDarwin())
|
||||
{
|
||||
const libtool = LibtoolStep.create(b, .{
|
||||
.name = name,
|
||||
.out_name = b.fmt("lib{s}-fat.a", .{name}),
|
||||
|
|
|
|||
Loading…
Reference in New Issue