const std = @import("std"); pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const force_build_rust = b.option(bool, "build-rust", "Always build Rust library from source") orelse false; const arch_str = @tagName(target.result.cpu.arch); const os_str = @tagName(target.result.os.tag); const abi = target.result.abi; const target_triple = if (abi == .none) b.fmt("{s}-{s}", .{ arch_str, os_str }) else b.fmt("{s}-{s}-{s}", .{ arch_str, os_str, @tagName(abi) }); 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 }); // --- Pre-built resolution --- // var prebuilt_lib_file: ?std.Build.LazyPath = null; var selected_lib_file: std.Build.LazyPath = undefined; 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 |_| {} } } 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; } else { // std.debug.print("building from source: {s}\n searched for prebuild at: {s}\n", .{ prebuilt_lib_path, prebuilt_lib_path }); 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", .gnueabi, .eabi => "armv7-unknown-linux-gnueabi", .musleabihf => "armv7-unknown-linux-musleabihf", .musleabi => "armv7-unknown-linux-musleabi", else => "armv7-unknown-linux-gnueabihf", } else blk: { const rust_target = build_crab.rust.Target.fromZig(zig_target) catch @panic("unable to convert target triple to Rust"); break :blk b.fmt("{f}", .{rust_target}); }; const build_dir = build_crab.addCargoBuild( b, .{ .manifest_path = b.path("Cargo.toml"), .cargo_args = if (optimize == .Debug) &.{} else &.{"--release"}, .rust_target = .{ .value = rust_target_str }, }, .{ .optimize = .ReleaseSafe, }, ); 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); }