fig-sys 5.0.0

FFI bindings and native library for fig (the comment-preserving JSON/YAML/TOML/… config engine). Used by the `fig` crate.
Documentation
const std = @import("std");
const Context = @import("src/build/Context.zig");
const Options = @import("src/build/Options.zig");
const artifacts = @import("src/build/artifacts.zig");
const tools = @import("src/build/tools.zig");
const tests = @import("src/build/tests.zig");
const checks = @import("src/build/checks.zig");

// The build graph lives in src/build/, split by role and wired together at the
// bottom of `build`:
//   * src/build/Context.zig   — the inputs every stage shares (target, optimize, …)
//   * src/build/Options.zig   — the `-D` knobs baked into `build_options`
//   * src/build/artifacts.zig — the fig lib, CLI, LSP, C ABI (static+shared), wasm/wasi
//   * src/build/tools.zig     — vendor-rust, gen-*-conformance, sync/check-figl, version-sync
//   * src/build/tests.zig     — test, conformance, fuzz, install-tests
//   * src/build/checks.zig    — abi/semver guards, rust/ts suites, the `check` gate
//
// The package-identity constants below stay HERE, not in Options.zig, and are
// handed to the rest of the graph via `Options.Versions`.

/// The one version every artifact ships under — the core, the CLI, the Rust
/// crates and both npm packages (see docs/VERSIONING.md) — parsed once from
/// `build.zig.zon`'s `.version`, so the C ABI's `fig_version*` accessors, `fig
/// version`, and the version-drift check all read from a single source.
const version = std.SemanticVersion.parse(@import("build.zig.zon").version) catch
    @compileError("invalid `.version` in build.zig.zon");

/// The binary C ABI contract version (see `FIG_ABI_VERSION` in bindings/c/include/fig.h).
/// Canonical source of truth — surfaced to the C ABI as `fig_abi_version()` and
/// pinned to the header macro by `zig build abi-check`. A monotonic counter,
/// bumped ONLY on a breaking ABI change (which fig's forward-compat policy makes
/// rare); decoupled from the marketing `.version` above so a feature release does
/// not move it. `zig build semver-check` requires it to increment whenever the C
/// ABI diff against the last release tag is breaking.
const abi_version: u8 = 3;

/// The current "epoch" — a marketing name that changes far less often than
/// `version`'s major (see docs/VERSIONING.md: "major releases are not
/// sacred," so this exists precisely to give users a stable, human-facing
/// handle across a run of otherwise-eager SemVer bumps). Purely cosmetic —
/// no compatibility contract, so it lives here as a bare constant (like
/// `abi_version`) rather than in build.zig.zon (a
/// toolchain-parsed package manifest with its own schema) or the C ABI (which
/// only ever exposes things a consumer might actually branch on). Surfaced
/// only by the CLI's `fig version`.
const epoch = "Texas Everbearing";

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const strip = b.option(bool, "strip", "Strip debug information") orelse (optimize == .ReleaseSmall);

    const ver: Options.Versions = .{
        .version = version,
        .abi = abi_version,
        .epoch = epoch,
    };

    // The user-facing `-D` configuration, baked into the one shared
    // `build_options` module every artifact imports.
    const cfg = Options.resolve(b);
    const fig_options = Options.addFigOptions(b, cfg, ver);
    const options_mod = fig_options.createModule();

    // The same module written out as a source file, for building the CLI
    // without a build system: a Zig compiled to wasm32-wasi has `build`
    // compiled out, and WASI preview 1 cannot spawn a build runner anyway, so
    // `build_options` has to arrive as a plain .zig file the `build-exe`
    // command line can name. Emitting it from `fig_options` rather than
    // hand-maintaining a copy is what keeps it from drifting. Attached to each
    // `v*` release by .github/workflows/release-binaries.yml.
    const wasi_options_step = b.step("wasi-options", "Write build_options.zig for a build-system-free build");
    wasi_options_step.dependOn(&b.addInstallFileWithDir(fig_options.getOutput(), .prefix, "build_options.zig").step);

    const ctx: Context = .{
        .b = b,
        .target = target,
        .optimize = optimize,
        .strip = strip,
        .cfg = cfg,
        .options_mod = options_mod,
        .ver = ver,
    };

    // Order matters only for the data handed downstream, not the build graph:
    // artifacts hands its lib/exe to tools & tests, and its static C ABI lib to
    // checks; tools & tests hand their gate steps to checks.
    const arts = artifacts.add(ctx);
    const tools_result = tools.add(ctx, arts);
    const tests_result = tests.add(ctx, arts);
    checks.add(ctx, arts, .{
        .check_figl_step = tools_result.check_figl_step,
        .validate_check_step = tools_result.validate_check_step,
        .vendor_check_step = tools_result.vendor_check_step,
        .version_check_step = tools_result.version_check_step,
        .test_step = tests_result.test_step,
        .conformance_step = tests_result.conformance_step,
    });
}