alef 0.115.7

Opinionated polyglot binding generator for Rust libraries
Documentation
{{ generated_header }}
use std::collections::BTreeSet;
use std::path::PathBuf;

fn main() {
    let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR unset"));
    let crate_name = std::env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME unset");
    let bridges = vec!["src/lib.rs"];
    let generated = swift_bridge_build::parse_bridges(bridges);
    if std::env::var("CARGO_CFG_TARGET_VENDOR").as_deref() == Ok("apple") {
        let swift = generated.concat_swift();
        // Swift owns these exports, which are linked after Cargo builds the cdylib. ~keep
        for name in swift_callback_exports(&swift) {
            println!("cargo:rustc-cdylib-link-arg=-Wl,-U,_{name}");
        }
    }
    generated.write_all_concatenated(out_dir, &crate_name);
    println!("cargo:rerun-if-changed=src/lib.rs");
}

fn swift_callback_exports(swift: &str) -> BTreeSet<&str> {
    let mut names = BTreeSet::new();
    for line in swift.lines().map(str::trim).filter(|line| line.starts_with("@_cdecl")) {
        let name = line
            .strip_prefix("@_cdecl(\"")
            .and_then(|rest| rest.strip_suffix("\")"))
            .expect("malformed swift-bridge @_cdecl export");
        assert!(
            !name.is_empty()
                && !name.chars().any(|character| {
                    character.is_control() || character.is_whitespace() || matches!(character, ',' | '"' | '\\')
                }),
            "invalid Swift callback export symbol"
        );
        assert!(names.insert(name), "duplicate Swift callback export symbol");
    }
    names
}