1use anyhow::{anyhow, Result};
2use pkg_config::Config;
3use bindgen::{MacroTypeVariation, NonCopyUnionStyle, EnumVariation, AliasVariation, FieldVisibilityKind, Builder};
4use std::{collections::HashSet, path::PathBuf, env::{var, set_var}};
5
6const OUT_DIR_ENV: &str = "OUT_DIR";
7const MINIMUM_VERSION: &str = "2024";
8
9pub fn build_with(config: &str) -> Result<()> {
12 set_var(config, "1");
13 build()
14}
15
16pub fn build() -> Result<()> {
18 let config = if var("CARGO_FEATURE_DYNAMIC_ILP64_GOMP").is_ok() {
19 "mkl-dynamic-ilp64-gomp"
20 } else if var("CARGO_FEATURE_DYNAMIC_ILP64_IOMP").is_ok() {
21 "mkl-dynamic-ilp64-iomp"
22 } else if var("CARGO_FEATURE_DYNAMIC_ILP64_SEQ").is_ok() {
23 "mkl-dynamic-ilp64-seq"
24 } else if var("CARGO_FEATURE_DYNAMIC_LP64_GOMP").is_ok() {
25 "mkl-dynamic-lp64-gomp"
26 } else if var("CARGO_FEATURE_DYNAMIC_LP64_IOMP").is_ok() {
27 "mkl-dynamic-lp64-iomp"
28 } else if var("CARGO_FEATURE_DYNAMIC_LP64_SEQ").is_ok() {
29 "mkl-dynamic-lp64-seq"
30 } else if var("CARGO_FEATURE_STATIC_ILP64_GOMP").is_ok() {
31 "mkl-static-ilp64-gomp"
32 } else if var("CARGO_FEATURE_STATIC_ILP64_IOMP").is_ok() {
33 "mkl-static-ilp64-iomp"
34 } else if var("CARGO_FEATURE_STATIC_ILP64_SEQ").is_ok() {
35 "mkl-static-ilp64-seq"
36 } else if var("CARGO_FEATURE_STATIC_LP64_GOMP").is_ok() {
37 "mkl-static-lp64-gomp"
38 } else if var("CARGO_FEATURE_STATIC_LP64_IOMP").is_ok() {
39 "mkl-static-lp64-iomp"
40 } else if var("CARGO_FEATURE_STATIC_LP64_SEQ").is_ok() {
41 "mkl-static-lp64-seq"
42 } else if var("CARGO_FEATURE_SDL").is_ok() {
43 "mkl-sdl"
44 } else {
45 return Err(anyhow::anyhow!("At least one of the following features must be enabled: dynamic-ilp64-gomp, dynamic-ilp64-iomp, dynamic-ilp64-seq, dynamic-lp64-gomp, dynamic-lp64-iomp, dynamic-lp64-seq, static-ilp64-gomp, static-ilp64-iomp, static-ilp64-seq, static-lp64-gomp, static-lp64-iomp, static-lp64-seq, sdl"));
46
47 };
48
49 let library = if config.contains("dynamic") {
50 Config::new()
51 .atleast_version(MINIMUM_VERSION)
52 .probe(config)?
53 } else {
54 Config::new()
55 .atleast_version(MINIMUM_VERSION)
56 .statik(true)
57 .probe(config)?
58 };
59
60 println!("cargo:warning={library:?}");
61
62 let lib_paths = library.link_files.iter()
63 .filter_map(|p| p.parent().map(|p| p.to_path_buf()))
64 .chain(library.link_paths.iter().map(|p| p.to_path_buf()))
65 .collect::<HashSet<_>>();
66
67 let ld_library_paths = lib_paths.iter()
68 .filter_map(|p| p.to_str())
69 .map(|p| p.to_string())
70 .collect::<Vec<_>>();
71
72 let include_path = library.include_paths
73 .first()
74 .ok_or_else(|| anyhow!("No include path found"))?;
75
76 let mkl_include_path = include_path
77 .join("mkl.h");
78
79 Builder::default()
80 .clang_arg(format!("-I{}", &include_path.to_str().ok_or_else(|| anyhow!("Invalid include path"))?))
81 .clang_arg("-fretain-comments-from-system-headers")
82 .clang_arg("-fparse-all-comments")
83 .clang_arg("-Wno-everything")
85 .default_visibility(FieldVisibilityKind::Public)
86 .default_alias_style(AliasVariation::TypeAlias)
87 .default_enum_style(EnumVariation::Rust {
88 non_exhaustive: false,
89 })
90 .default_macro_constant_type(MacroTypeVariation::Unsigned)
91 .default_non_copy_union_style(NonCopyUnionStyle::BindgenWrapper)
92 .derive_default(true)
93 .derive_hash(true)
94 .derive_partialord(true)
95 .derive_ord(true)
96 .derive_eq(true)
97 .derive_partialeq(true)
98 .generate_comments(true)
99 .blocklist_function("strtold")
101 .blocklist_function("qecvt")
102 .blocklist_function("qfcvt")
103 .blocklist_function("qgcvt")
104 .blocklist_function("qecvt_r")
105 .blocklist_function("qfcvt_r")
106 .header(mkl_include_path.to_str().ok_or_else(|| anyhow!("Invalid include path"))?)
107 .generate()
108 .map_err(|e| anyhow!("Failed to generate bindings: {}", e))?
109 .write_to_file(PathBuf::from(var(OUT_DIR_ENV)?).join("bindings.rs"))?;
110
111 if cfg!(feature = "dynamic-ilp64-gomp") || cfg!(feature = "dynamic-lp64-gomp") || cfg!(feature = "static-ilp64-gomp") || cfg!(feature = "static-lp64-gomp") {
113 println!("cargo:rustc-link-lib=gomp");
114 }
115
116 if cfg!(feature = "static-ilp64-iomp") || cfg!(feature = "static-lp64-iomp") {
118 println!("cargo:rustc-link-lib=iomp5");
119 }
120
121 println!("cargo:rustc-env=LD_LIBRARY_PATH={}", ld_library_paths.join(":"));
122
123 Ok(())
124}