FEMM/crates/femm-sys/build.rs

76 lines
3.2 KiB
Rust

//! builds the engine archives and generates FFI bindings for femm-sys.
use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() {
let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let repo_root = manifest.parent().unwrap().parent().unwrap().to_path_buf();
let ffi_dir = repo_root.join("ffi");
let build_dir = repo_root.join("build").join("ffi");
// re-run on changes to any FFI header, build script, or solver source dir.
println!("cargo:rerun-if-changed={}", ffi_dir.display());
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/macos/build_ffi.sh").display());
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/windows/build_ffi.ps1").display());
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/windows/_toolchain.ps1").display());
for engine in ["fkn", "belasolv", "csolv", "hsolv", "liblua", "compat"] {
println!("cargo:rerun-if-changed={}", repo_root.join(engine).display());
}
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
let status = match target_os.as_str() {
"macos" => Command::new("bash")
.arg(repo_root.join("scripts/macos/build_ffi.sh"))
.status()
.expect("failed to invoke bash for engine build script"),
"windows" => {
let script = repo_root.join("scripts/windows/build_ffi.ps1");
Command::new("pwsh")
.args([
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
])
.arg(&script)
.status()
.expect("failed to invoke pwsh for engine build script")
}
other => panic!("femm-sys: no engine build script wired up for target_os={other}"),
};
if !status.success() {
panic!("engine build script exited with {status}");
}
println!("cargo:rustc-link-search=native={}", build_dir.display());
for lib in ["femm_mag", "femm_elec", "femm_heat", "femm_curr"] {
println!("cargo:rustc-link-lib=static={lib}");
}
match (target_os.as_str(), target_env.as_str()) {
("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
("windows", "gnullvm") => println!("cargo:rustc-link-lib=dylib=c++"),
("windows", "msvc") => { /* MSVC links the C++ runtime automatically */ }
_ => println!("cargo:rustc-link-lib=dylib=stdc++"),
}
let bindings = bindgen::Builder::default()
.header(manifest.join("wrapper.h").to_str().unwrap())
.clang_arg(format!("-I{}", ffi_dir.display()))
.allowlist_function("femm_.*")
.allowlist_type("Femm.*")
.allowlist_var("FEMM_.*")
.derive_default(true)
.derive_copy(true)
.derive_debug(true)
.layout_tests(false)
.generate()
.expect("bindgen failed to generate FFI bindings");
let out = PathBuf::from(env::var("OUT_DIR").unwrap()).join("bindings.rs");
bindings.write_to_file(&out).expect("failed to write bindings.rs");
}