prismqueer 0.1.1

The spectral-triple substrate — five operations (focus, project, split, shift, settle), the Prism trait, zero deps. The foundation.
Documentation
fn main() {
    #[cfg(feature = "lapack")]
    build_fortran();
}

#[cfg(feature = "lapack")]
fn build_fortran() {
    use std::process::Command;

    let saved = save_and_clear_c_flags();

    cc::Build::new()
        .compiler("gfortran")
        .file("native/prism.f90")
        .file("native/spectral.f90")
        .flag("-fPIC")
        .flag("-O2")
        .compile("fortran_ops");

    restore_c_flags(saved);

    let lib_name = if cfg!(target_os = "macos") {
        "libgfortran.dylib"
    } else {
        "libgfortran.so"
    };
    let output = Command::new("gfortran")
        .args([format!("-print-file-name={}", lib_name)])
        .output()
        .expect("gfortran must be in PATH");
    let lib_path = String::from_utf8(output.stdout).unwrap();
    let lib_path = lib_path.trim();
    if let Some(dir) = std::path::Path::new(lib_path).parent() {
        let d = dir.display().to_string();
        if !d.is_empty() {
            println!("cargo:rustc-link-search=native={}", d);
        }
    }
    println!("cargo:rustc-link-lib=gfortran");

    if cfg!(target_os = "macos") {
        println!("cargo:rustc-link-lib=framework=Accelerate");
    } else {
        println!("cargo:rustc-link-lib=lapack");
        println!("cargo:rustc-link-lib=blas");
    }
}

#[cfg(feature = "lapack")]
const C_FLAG_VARS: &[&str] = &["CFLAGS", "CXXFLAGS", "NIX_CFLAGS_COMPILE"];

#[cfg(feature = "lapack")]
fn save_and_clear_c_flags() -> Vec<(&'static str, Option<String>)> {
    C_FLAG_VARS
        .iter()
        .map(|&var| {
            let val = std::env::var(var).ok();
            unsafe { std::env::remove_var(var) };
            (var, val)
        })
        .collect()
}

#[cfg(feature = "lapack")]
fn restore_c_flags(saved: Vec<(&'static str, Option<String>)>) {
    for (var, val) in saved {
        match val {
            Some(v) => unsafe { std::env::set_var(var, v) },
            None => unsafe { std::env::remove_var(var) },
        }
    }
}