use std::path::PathBuf;
use wolfram_app_discovery::{WolframApp, WolframVersion};
fn main() {
wolfram_app_discovery::config::set_print_cargo_build_script_instructions(true);
if std::env::var("DOCS_RS").is_ok() {
let bindings_path = make_bindings_path("13.0.0", "MacOSX-x86-64");
println!(
"cargo:rustc-env=CRATE_WOLFRAM_LIBRARYLINK_SYS_BINDINGS={}",
bindings_path.display()
);
return;
}
let app = WolframApp::try_default().expect("unable to locate WolframApp");
let bindings_path = use_generated_bindings(&app);
println!(
"cargo:rustc-env=CRATE_WOLFRAM_LIBRARYLINK_SYS_BINDINGS={}",
bindings_path.display()
);
}
fn use_generated_bindings(app: &WolframApp) -> PathBuf {
let c_includes = app
.library_link_c_includes_path()
.expect("unable to get LibraryLink C includes directory");
println!(
"cargo:warning=info: generating LibraryLink bindings from: {}",
c_includes.display()
);
let out_path =
PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("LibraryLink_bindings.rs");
generate_and_save_bindings_to_file(&c_includes, &out_path);
out_path
}
fn generate_and_save_bindings_to_file(c_includes: &PathBuf, out_path: &PathBuf) {
assert!(c_includes.ends_with("SystemFiles/IncludeFiles/C/"));
assert!(c_includes.is_dir());
assert!(c_includes.is_absolute());
#[rustfmt::skip]
let bindings = bindgen::builder()
.header(c_includes.join("WolframLibrary.h").display().to_string())
.header(c_includes.join("WolframNumericArrayLibrary.h").display().to_string())
.header(c_includes.join("WolframIOLibraryFunctions.h").display().to_string())
.header(c_includes.join("WolframImageLibrary.h").display().to_string())
.header(c_includes.join("WolframSparseLibrary.h").display().to_string())
.generate_comments(true)
.clang_arg("-fretain-comments-from-system-headers")
.clang_arg("-fparse-all-comments")
.constified_enum_module("MNumericArray_Data_Type")
.constified_enum_module("MNumericArray_Convert_Method")
.constified_enum_module("MImage_Data_Type")
.constified_enum_module("MImage_CS_Type")
.rustfmt_bindings(true)
.generate()
.expect("unable to generate Rust bindings to Wolfram LibraryLink using bindgen");
std::fs::create_dir_all(out_path.parent().unwrap())
.expect("failed to create parent directories for generating bindings file");
bindings
.write_to_file(out_path)
.expect("failed to write Rust bindings with IO error");
}
#[allow(dead_code)]
fn use_pregenerated_bindings(wolfram_version: &WolframVersion) -> PathBuf {
let system_id =
wolfram_app_discovery::system_id_from_target(&std::env::var("TARGET").unwrap())
.expect("unable to get System ID for target system");
let bindings_path = make_bindings_path(&wolfram_version.to_string(), system_id);
println!("cargo:rerun-if-changed={}", bindings_path.display());
if !bindings_path.is_file() {
println!(
"
==== ERROR: wolfram-library-link-sys =====
Rust bindings for Wolfram LibraryLink for target configuration:
WolframVersion: {}
SystemID: {}
have not been pre-generated.
See wolfram-library-link-sys/generated/ for a listing of currently available targets.
=========================================
",
wolfram_version, system_id
);
panic!("<See printed error>");
}
bindings_path
}
fn make_bindings_path(wolfram_version: &str, system_id: &str) -> PathBuf {
let bindings_path = PathBuf::from("generated")
.join(wolfram_version)
.join(system_id)
.join("LibraryLink_bindings.rs");
let absolute_bindings_path =
PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join(&bindings_path);
absolute_bindings_path
}