use cmake::Config; use std::path::{Path, PathBuf}; /// Allow x86_64 <-> aarch64 cross compilation on macOS /// https://cmake.org/cmake/help/latest/command/try_run.html#behavior-when-cross-compiling fn setup_macos_cross_compile(config: &mut Config) { let host_triple = std::env::var("HOST").unwrap(); let target_triple = std::env::var("TARGET").unwrap(); let host_triple = host_triple.split('-').collect::>(); let target_triple = target_triple.split('-').collect::>(); if host_triple[1] == "apple" && target_triple[1] == "apple" && host_triple[0] != target_triple[0] { config.define("SEAL_MEMSET_S_FOUND_EXITCODE", "0"); config.define("SEAL_MEMSET_S_FOUND_EXITCODE__TRYRUN_OUTPUT", ""); config.define("SEAL___BUILTIN_CLZLL_FOUND_EXITCODE", "0"); config.define("SEAL___BUILTIN_CLZLL_FOUND_EXITCODE__TRYRUN_OUTPUT", ""); config.define("SEAL__ADDCARRY_U64_FOUND_EXITCODE", "0"); config.define("SEAL__ADDCARRY_U64_FOUND_EXITCODE__TRYRUN_OUTPUT", ""); config.define("SEAL__SUBBORROW_U64_FOUND_EXITCODE", "0"); config.define("SEAL__SUBBORROW_U64_FOUND_EXITCODE__TRYRUN_OUTPUT", ""); } } fn compile_native(profile: &str, out_path: &Path) { let hexl = if std::env::var("CARGO_FEATURE_HEXL").is_ok() { "ON" } else { "OFF" }; let forbid_transparent_ciphertexts = if std::env::var("CARGO_FEATURE_TRANSPARENT_CIPHERTEXTS").is_ok() { "OFF" } else { "ON" }; let mut builder = Config::new("SEAL"); builder .define("CMAKE_BUILD_TYPE", profile) .define("CMAKE_CXX_FLAGS_RELEASE", "-DNDEBUG -O3") .define("CMAKE_C_FLAGS_RELEASE", "-DNDEBUG -O3") .define("SEAL_USE_GAUSSIAN_NOISE", "ON") .define("SEAL_BUILD_STATIC_SEAL_C", "ON") .define("SEAL_USE_INTEL_HEXL", hexl) .define("SEAL_BUILD_DEPS", "ON") .define("SEAL_BUILD_SEAL_C", "ON") .define("SEAL_BUILD_BENCH", "OFF") .define("SEAL_BUILD_EXAMPLES", "OFF") .define("SEAL_BUILD_TESTS", "OFF") .define("SEAL_USE_CXX17", "ON") .define("SEAL_USE_INTRIN", "ON") .define("SEAL_USE_MSGSL", "OFF") .define("SEAL_USE_ZLIB", "ON") .define("SEAL_USE_ZSTD", "ON") .define( "SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT", forbid_transparent_ciphertexts, ); setup_macos_cross_compile(&mut builder); let dst = builder.build(); let out_path_suffix = if std::env::var("CARGO_CFG_WINDOWS").is_ok() { profile } else { "" }; // Tell cargo to look for shared libraries in the specified directory println!( "cargo:rustc-link-search=native={}/build/lib/{}", dst.display(), out_path_suffix ); // Tell cargo to tell rustc to link the static library seal. println!("cargo:rustc-link-lib=static=sealc-4.0"); println!("cargo:rustc-link-lib=static=seal-4.0"); println!("-I{}", out_path.join("include").display()); } fn main() { // debug/release let profile = std::env::var("PROFILE").expect("Failed to get build profile"); let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let target = std::env::var("TARGET").expect("Failed to get target"); println!("cargo:rerun-if-changed=SEAL"); let profile = if profile == "release" { "Release" } else if profile == "debug" { "Debug" } else { panic!("Unknown profile type {}", profile); }; compile_native(profile, &out_path); let mut builder = bindgen::builder() .clang_arg(format!("-I{}", out_path.join("include/SEAL-3.7").display())) .clang_arg("-ISEAL/native/src") .clang_arg("-xc++") .clang_arg("-std=c++17"); if target == "wasm32-unknown-emscripten" { // Bindgen appears to be broken under wasm. Just generate bindings with // the host's target. builder = builder .clang_arg("-target") .clang_arg("aarch64-apple-darwin") .detect_include_paths(false); } let builder = builder .detect_include_paths(true) .header("bindgen_wrapper.h") .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) .allowlist_function("BatchEncoder_.*") .allowlist_function("Ciphertext_.*") .allowlist_function("CKKSEncoder_.*") .allowlist_function("CoeffModulus_.*") .allowlist_function("ContextData_.*") .allowlist_function("Decryptor_.*") .allowlist_function("EPQ_.*") .allowlist_function("EncParams_.*") .allowlist_function("Encryptor_.*") .allowlist_function("Evaluator_.*") .allowlist_function("GaloisKeys_.*") .allowlist_function("KeyGenerator_.*") .allowlist_function("KSwitchKeys_.*") .allowlist_function("MemoryManager_.*") .allowlist_function("MemoryPoolHandle_.*") .allowlist_function("Modulus_.*") .allowlist_function("Plaintext_.*") .allowlist_function("PublicKey_.*") .allowlist_function("RelinKeys_.*") .allowlist_function("SEALContext_.*") .allowlist_function("SecretKey_.*") .allowlist_function("Serialization_.*") .allowlist_function("PolynomialArray_.*") .allowlist_function("ValCheck_.*"); let bindings = builder.generate().expect("Failed to generate bindings"); bindings .write_to_file(out_path.join("bindings.rs")) .expect("Failed to write bindings"); }