refactor: use isolated package per targets

This commit is contained in:
Nurul Huda (Apon) 2026-07-16 04:33:16 +06:00
parent cfb111fb74
commit 65cfa18d63
No known key found for this signature in database
GPG key ID: 5D3F1DE2855A2F79
6 changed files with 283 additions and 69 deletions

View file

@ -184,7 +184,7 @@ jobs:
run: |
cd lib
mkdir -p dist
tar -czf "dist/${{ matrix.target }}.tar.gz" -C zig-out/lib .
tar -czf "dist/${{ matrix.target }}.tar.gz" -C "zig-out/lib/${{ matrix.target }}" .
- name: Upload Artifact
uses: actions/upload-artifact@v4

View file

@ -51,18 +51,14 @@ exe.root_module.addImport("temporalz", temporalz.module("temporalz"));
Prebuilt libraries are included for the following platforms:
- `x86_64-macos`
- `aarch64-macos`
- `x86_64-linux-gnu`
- `aarch64-linux-gnu`
- `x86_64-windows-gnu`
- `aarch64-windows-gnu`
- `wasm32-freestanding`
- `wasm32-wasi`
- `x86_64-linux-musl`
- `aarch64-linux-musl`
- `aarch64-linux-android`
- `aarch64-ios`
- `x86_64-macos`, `aarch64-macos`
- `x86_64-linux-gnu`, `aarch64-linux-gnu`, `x86-linux-gnu`, `arm-linux-gnueabihf`
- `loongarch64-linux-gnu`, `powerpc64le-linux-gnu`, `riscv64-linux-gnu`, `s390x-linux-gnu`
- `x86_64-windows-gnu`, `aarch64-windows-gnu`, `x86-windows-gnu`
- `x86_64-freebsd`, `x86_64-netbsd`
- `wasm32-freestanding`, `wasm32-wasi`
- `x86_64-linux-musl`, `aarch64-linux-musl`
- `aarch64-linux-android`, `aarch64-ios`
For other platforms, the library will build from source; you need the Rust toolchain installed.

View file

@ -1,4 +1,5 @@
const std = @import("std");
const targets = @import("targets.zig");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
@ -12,38 +13,65 @@ pub fn build(b: *std.Build) !void {
b.fmt("{s}-{s}", .{ arch_str, os_str })
else
b.fmt("{s}-{s}-{s}", .{ arch_str, os_str, @tagName(abi) });
const prebuilt_name = targets.prebuiltName(b, target);
const lib_name = if (target.result.os.tag == .windows and abi == .msvc)
"temporal_capi.lib"
else
"libtemporal_capi.a";
const prebuilt_lib_path = b.fmt("{s}/{s}", .{ target_triple, lib_name });
// --- Module --- //
const mod = b.addModule("libtemporal", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
// --- Pre-built resolution --- //
var prebuilt_lib_file: ?std.Build.LazyPath = null;
var selected_lib_file: std.Build.LazyPath = undefined;
const temporal_rs = b.dependency("temporal_rs", .{
.target = target,
.optimize = optimize,
});
if (!force_build_rust) {
const libtemporal_dep = b.lazyDependency("prebuilt_libtemporal", .{});
if (libtemporal_dep) |dep| {
const lib_file_candidate = dep.path(prebuilt_lib_path);
if (dep.builder.root.access(b.graph.io, prebuilt_lib_path, .{})) {
prebuilt_lib_file = lib_file_candidate;
} else |_| {}
}
const translated = b.addTranslateC(.{
.root_source_file = b.path("src/lib.h"),
.target = target,
.optimize = optimize,
.link_libc = false,
});
translated.addIncludePath(temporal_rs.path("temporal_capi/bindings/c"));
translated.addIncludePath(b.path("src/stubs/c_headers"));
mod.addImport("lib", translated.createModule());
// --- Rust Misc Deps --- //
if (target.result.os.tag == .windows) mod.linkSystemLibrary("userenv", .{});
const unwind_stubs = b.addLibrary(.{ .linkage = .static, .name = "unwind_stubs", .root_module = b.createModule(.{
.root_source_file = b.path("src/stubs/unwind.zig"),
.target = target,
.optimize = optimize,
}) });
mod.linkLibrary(unwind_stubs);
// --- Steps: update prebuilt dependency hashes --- //
{
const update_step = b.step("update", "Fetch prebuilt packages and update build.zig.zon");
addPrebuiltDependencyFetches(b, update_step);
}
if (prebuilt_lib_file) |plf| {
// std.debug.print("Using pre-built temporal_capi library from downloaded artifact at: {s}\n", .{prebuilt_lib_path});
selected_lib_file = plf;
// --- Static lib resolution (prebuilt or source) --- //
var selected_lib_file: std.Build.LazyPath = undefined;
if (!force_build_rust and targets.isDeclared(prebuilt_name)) {
const prebuilt_dep = b.lazyDependency(prebuilt_name, .{}) orelse {
return;
};
std.log.info("using prebuilt libtemporal for {s}", .{prebuilt_name});
selected_lib_file = prebuilt_dep.path(lib_name);
} else {
// std.debug.print("building from source: {s}\n searched for prebuild at: {s}\n", .{ prebuilt_lib_path, prebuilt_lib_path });
std.log.info("building libtemporal from source for {s}, requires Rust toolchain", .{target_triple});
const build_crab = @import("build_crab");
var zig_target = target.result;
if (zig_target.os.tag == .windows) zig_target.abi = .gnu;
// Zig's baseline `.arm` maps to Rust `arm-*`, but rustup ships `armv7-*`.
const rust_target_str: []const u8 = if (zig_target.cpu.arch == .arm and zig_target.os.tag == .linux)
switch (zig_target.abi) {
.gnueabihf, .eabihf => "armv7-unknown-linux-gnueabihf",
@ -71,39 +99,44 @@ pub fn build(b: *std.Build) !void {
selected_lib_file = build_dir.path(b, lib_name);
}
// --- Install Step (for publishing) --- //
const install_lib = b.addInstallFile(selected_lib_file, b.fmt("lib/{s}/{s}", .{ target_triple, lib_name }));
b.getInstallStep().dependOn(&install_lib.step);
// --- Zig Module --- //
const mod = b.addModule("libtemporal", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
const temporal_rs = b.dependency("temporal_rs", .{
.target = target,
.optimize = optimize,
});
const translated = b.addTranslateC(.{
.root_source_file = b.path("src/lib.h"),
.target = target,
.optimize = optimize,
.link_libc = false,
});
translated.addIncludePath(temporal_rs.path("temporal_capi/bindings/c"));
translated.addIncludePath(b.path("src/stubs/c_headers"));
mod.addImport("lib", translated.createModule());
mod.addObjectFile(selected_lib_file);
// --- Rust Misc Deps --- //
if (target.result.os.tag == .windows) mod.linkSystemLibrary("userenv", .{});
const unwind_stubs = b.addLibrary(.{ .linkage = .static, .name = "unwind_stubs", .root_module = b.createModule(.{
.root_source_file = b.path("src/stubs/unwind.zig"),
.target = target,
.optimize = optimize,
}) });
mod.linkLibrary(unwind_stubs);
// --- Install Step (for publishing) --- //
const install_lib = b.addInstallFile(selected_lib_file, b.fmt("lib/{s}/{s}", .{ prebuilt_name, lib_name }));
b.getInstallStep().dependOn(&install_lib.step);
}
fn addPrebuiltDependencyFetches(b: *std.Build, parent: *std.Build.Step) void {
var prev_save: ?*std.Build.Step = null;
inline for (targets.config.targets) |target_triple| {
const url = targets.releaseUrl(b, target_triple);
const fetch = b.addSystemCommand(&.{ b.graph.zig_exe, "fetch", url });
fetch.setName(b.fmt("fetch {s}", .{target_triple}));
fetch.setCwd(b.path("."));
fetch.has_side_effects = true;
fetch.expectExitCode(0);
_ = fetch.captureStdErr(.{});
const save = b.addSystemCommand(&.{
b.graph.zig_exe,
"fetch",
b.fmt("--save={s}", .{target_triple}),
url,
});
save.setName(b.fmt("save {s}", .{target_triple}));
save.setCwd(b.path("."));
save.has_side_effects = true;
save.expectExitCode(0);
_ = save.captureStdErr(.{});
save.step.dependOn(&fetch.step);
if (prev_save) |prev| {
save.step.dependOn(prev);
}
parent.dependOn(&save.step);
prev_save = &save.step;
}
}

View file

@ -7,19 +7,121 @@
.url = "git+https://github.com/boa-dev/temporal?ref=v0.2.4#a5cebbcce231552bf6ed985d7ea13b0c7b195f02",
.hash = "N-V-__8AALjnOQBiCk4NffYgEewZ5v9qlLlDyXO22FIyzNdf",
},
.prebuilt_libtemporal = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.3/libtemporal.tar.gz",
.hash = "N-V-__8AADYZ_AXnqpmkTa49ZQ6lEQlDXWRLthyxEbgse3Hi",
.lazy = true,
},
.build_crab = .{
.url = "git+https://github.com/nurulhudaapon/build.crab?ref=zig-dev#69a630f8fa9ccca37a8ba2e898e7934e3b5b8fe2",
.hash = "build_crab-0.2.1-U0id_zfKAAAvOuam-kPYKMuEQpHuEBjrP96uQCVj94yr",
},
.@"aarch64-ios" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-ios.tar.gz",
.hash = "N-V-__8AAJAyaADZvWvrmaGR5reVCH4y8JZ3-Gfxu_9-pcHB",
.lazy = true,
},
.@"aarch64-linux-android" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-android.tar.gz",
.hash = "N-V-__8AAKYEkwCQonhHp5MAYaRE8IFcWN493Y2a5nqWJmF7",
.lazy = true,
},
.@"aarch64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-gnu.tar.gz",
.hash = "N-V-__8AAGSQjQDYfN0voDb4c1sCM374u570U8hcEJYoAoTc",
.lazy = true,
},
.@"aarch64-linux-musl" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-linux-musl.tar.gz",
.hash = "N-V-__8AAE7bjwA2arkXXgbgaMe8oHdmJEez8y2XFeCUvSnn",
.lazy = true,
},
.@"aarch64-macos" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-macos.tar.gz",
.hash = "N-V-__8AAFBxZwC9MEuiOD8EihBoSl_00IDUJnpQsjmnpkmK",
.lazy = true,
},
.@"aarch64-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/aarch64-windows-gnu.tar.gz",
.hash = "N-V-__8AADKDagD1bmYDywq4IZPBo2la8m1xzSObPCsxyfmW",
.lazy = true,
},
.@"arm-linux-gnueabihf" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/arm-linux-gnueabihf.tar.gz",
.hash = "N-V-__8AAIAAfgDYWro4rWudgosfdPK1tzxLe77uoRBtL4rl",
.lazy = true,
},
.@"loongarch64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/loongarch64-linux-gnu.tar.gz",
.hash = "N-V-__8AAEKptADVBZFKw7ZKvLurwzp_WA-FD-OwZFgEMf4q",
.lazy = true,
},
.@"powerpc64le-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/powerpc64le-linux-gnu.tar.gz",
.hash = "N-V-__8AAKwdfQDZIHVuhOtUOs9tKx-RJCM_1HnX-FwGA0l2",
.lazy = true,
},
.@"riscv64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/riscv64-linux-gnu.tar.gz",
.hash = "N-V-__8AAPBiogBQe_5VZhzDgpZrfwuzfj_54IyUFK2igsQo",
.lazy = true,
},
.@"s390x-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/s390x-linux-gnu.tar.gz",
.hash = "N-V-__8AAEiKkwC4qkNJoOuzgxHuS_q46SIbqITuODu9Hz3Q",
.lazy = true,
},
.@"wasm32-freestanding" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/wasm32-freestanding.tar.gz",
.hash = "N-V-__8AACjsTwB3jX1mva0svtTn39kCz5aabikQbczLJlp9",
.lazy = true,
},
.@"wasm32-wasi" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/wasm32-wasi.tar.gz",
.hash = "N-V-__8AAPbTQADoTDaLXmk3KlebN5pZWX-eXhD6BLPJuxpt",
.lazy = true,
},
.@"x86-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86-linux-gnu.tar.gz",
.hash = "N-V-__8AALzUbwBdOV8TmU7vPbofrSgkCz70GG0SwvHZGWEZ",
.lazy = true,
},
.@"x86-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86-windows-gnu.tar.gz",
.hash = "N-V-__8AAAgSYQAjy_QNLkxQurUPnbT8s4fNjunaYgPQjiwB",
.lazy = true,
},
.@"x86_64-freebsd" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-freebsd.tar.gz",
.hash = "N-V-__8AAJAFkQCAz3khARx91vZb6HMPqV3oBdmJM8kaxd9Y",
.lazy = true,
},
.@"x86_64-linux-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-linux-gnu.tar.gz",
.hash = "N-V-__8AACAdiQB3WUysJXS42gsJZdpzna_04l6omEQGzJZa",
.lazy = true,
},
.@"x86_64-linux-musl" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-linux-musl.tar.gz",
.hash = "N-V-__8AAGhKiwDlW7Ecy5CJf7-PEGSdDgr4VnCNLkl9cery",
.lazy = true,
},
.@"x86_64-macos" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-macos.tar.gz",
.hash = "N-V-__8AAHDyZwCPo6HVOYeFWas2bcTqi67vJuxoL2huROlC",
.lazy = true,
},
.@"x86_64-netbsd" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-netbsd.tar.gz",
.hash = "N-V-__8AAL7_lgBmD0lfXqzAxRdjDiPLi6bgLvnVVbQszw3p",
.lazy = true,
},
.@"x86_64-windows-gnu" = .{
.url = "https://github.com/nurulhudaapon/temporalz/releases/download/v0.2.4/x86_64-windows-gnu.tar.gz",
.hash = "N-V-__8AAD5eTQDfQ9ddNZh3g8e6SaA9CnVSQRMozhHs_jWt",
.lazy = true,
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"targets.zon",
"targets.zig",
"src",
},
}

57
lib/targets.zig Normal file
View file

@ -0,0 +1,57 @@
const std = @import("std");
const builtin = @import("builtin");
pub const config = @import("targets.zon");
const manifest = @import("build.zig.zon");
/// Zig `-Dtarget` triple for the host platform's prebuilt dependency name.
pub fn depName() []const u8 {
const triple = targetTripleFromBuiltin();
if (!isDeclared(triple)) {
@compileError(std.fmt.comptimePrint(
"no prebuilt libtemporal for host {s}",
.{triple},
));
}
return triple;
}
pub fn prebuiltName(b: *std.Build, target: std.Build.ResolvedTarget) []const u8 {
const arch = @tagName(target.result.cpu.arch);
const os = target.result.os.tag;
const abi = target.result.abi;
if (os == .wasi and (abi == .musl or abi == .none))
return b.fmt("{s}-wasi", .{arch});
if (abi == .none)
return b.fmt("{s}-{s}", .{ arch, @tagName(os) });
return b.fmt("{s}-{s}-{s}", .{ arch, @tagName(os), @tagName(abi) });
}
pub fn isDeclared(target_triple: []const u8) bool {
inline for (config.targets) |supported| {
if (std.mem.eql(u8, supported, target_triple)) {
return comptime @hasField(@TypeOf(manifest.dependencies), supported);
}
}
return false;
}
pub fn releaseUrl(b: *std.Build, target_triple: []const u8) []const u8 {
return b.fmt(
"https://github.com/nurulhudaapon/temporalz/releases/download/v{s}/{s}.tar.gz",
.{ config.version, target_triple },
);
}
fn targetTripleFromBuiltin() []const u8 {
if (builtin.os.tag == .wasi and (builtin.abi == .musl or builtin.abi == .none))
return std.fmt.comptimePrint("{s}-wasi", .{@tagName(builtin.cpu.arch)});
const abi = builtin.abi;
return if (abi == .none)
std.fmt.comptimePrint("{s}-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) })
else
std.fmt.comptimePrint("{s}-{s}-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag), @tagName(abi) });
}

26
lib/targets.zon Normal file
View file

@ -0,0 +1,26 @@
.{
.version = "0.2.4",
.targets = .{
"x86_64-macos",
"aarch64-macos",
"x86_64-linux-gnu",
"aarch64-linux-gnu",
"x86-linux-gnu",
"arm-linux-gnueabihf",
"loongarch64-linux-gnu",
"powerpc64le-linux-gnu",
"riscv64-linux-gnu",
"s390x-linux-gnu",
"x86_64-windows-gnu",
"aarch64-windows-gnu",
"x86-windows-gnu",
"x86_64-freebsd",
"x86_64-netbsd",
"wasm32-freestanding",
"wasm32-wasi",
"x86_64-linux-musl",
"aarch64-linux-musl",
"aarch64-linux-android",
"aarch64-ios",
},
}