node-app-api 5.22.1

Shared types and C ABI definitions for the Node-App host API v1
Documentation
//! Build script for `node-app-api` (T124).
//!
//! Generates the host ABI v1 C header at
//! `core/host-abi-v1/include/node-host-api-v1.h` from the FFI types
//! declared in `src/ffi.rs` and `src/context.rs`.
//!
//! The header is committed to git so downstream consumers do not need
//! `cbindgen` installed at build time. Re-run by touching one of the
//! source files or running `cargo build -p node-app-api`.

use std::env;
use std::path::PathBuf;

fn main() {
    // Re-run only when the FFI surface or this script changes.
    println!("cargo:rerun-if-changed=src/ffi.rs");
    println!("cargo:rerun-if-changed=src/context.rs");
    println!("cargo:rerun-if-changed=src/types.rs");
    println!("cargo:rerun-if-changed=src/lib.rs");
    println!("cargo:rerun-if-changed=cbindgen.toml");
    println!("cargo:rerun-if-changed=build.rs");

    // Allow opting out (e.g. for `cargo publish` dry-run sandboxes that strip
    // the workspace context, or downstream builds that should not touch the
    // committed header).
    if env::var_os("NODE_APP_API_SKIP_CBINDGEN").is_some() {
        println!("cargo:warning=node-app-api: skipping cbindgen (NODE_APP_API_SKIP_CBINDGEN set)");
        return;
    }

    let crate_dir = match env::var("CARGO_MANIFEST_DIR") {
        Ok(dir) => PathBuf::from(dir),
        Err(_) => {
            println!("cargo:warning=node-app-api: CARGO_MANIFEST_DIR not set, skipping cbindgen");
            return;
        }
    };

    // Resolve `core/host-abi-v1/include/node-host-api-v1.h` relative to this
    // crate's manifest dir (`<repo>/sdk/api`). If the path cannot be
    // resolved (e.g. crate is being published outside the workspace), skip
    // header regeneration silently.
    let workspace_root = match crate_dir.parent().and_then(|p| p.parent()) {
        Some(p) => p.to_path_buf(),
        None => {
            println!(
                "cargo:warning=node-app-api: cannot resolve workspace root from {}, skipping cbindgen",
                crate_dir.display()
            );
            return;
        }
    };

    let header_dir = workspace_root.join("core").join("host-abi-v1").join("include");
    let header_path = header_dir.join("node-host-api-v1.h");

    if !header_dir.exists() {
        if let Err(err) = std::fs::create_dir_all(&header_dir) {
            println!(
                "cargo:warning=node-app-api: failed to create {}: {}; skipping cbindgen",
                header_dir.display(),
                err
            );
            return;
        }
    }

    let config = match cbindgen::Config::from_file(crate_dir.join("cbindgen.toml")) {
        Ok(cfg) => cfg,
        Err(err) => {
            println!(
                "cargo:warning=node-app-api: failed to load cbindgen.toml: {}",
                err
            );
            return;
        }
    };

    match cbindgen::Builder::new()
        .with_crate(&crate_dir)
        .with_config(config)
        .generate()
    {
        Ok(bindings) => {
            bindings.write_to_file(&header_path);
            println!(
                "cargo:warning=node-app-api: regenerated {}",
                header_path.display()
            );
        }
        Err(err) => {
            // Don't fail the build for header generation issues — the
            // committed header is the source of truth for consumers.
            println!(
                "cargo:warning=node-app-api: cbindgen generation failed: {}",
                err
            );
        }
    }
}