use std::env; use std::path::Path; use bindgen::MacroTypeVariation; // Keep in sync with the list in include/openssl/opensslconf.h const OSSL_CONF_DEFINES: &[&str] = &[ "OPENSSL_NO_ASYNC", "OPENSSL_NO_BF", "OPENSSL_NO_BLAKE2", "OPENSSL_NO_BUF_FREELISTS", "OPENSSL_NO_CAMELLIA", "OPENSSL_NO_CAPIENG", "OPENSSL_NO_CAST", "OPENSSL_NO_CMS", "OPENSSL_NO_COMP", "OPENSSL_NO_CT", "OPENSSL_NO_DANE", "OPENSSL_NO_DEPRECATED", "OPENSSL_NO_DGRAM", "OPENSSL_NO_DYNAMIC_ENGINE", "OPENSSL_NO_EC_NISTP_64_GCC_128", "OPENSSL_NO_EC2M", "OPENSSL_NO_EGD", "OPENSSL_NO_ENGINE", "OPENSSL_NO_GMP", "OPENSSL_NO_GOST", "OPENSSL_NO_HEARTBEATS", "OPENSSL_NO_HW", "OPENSSL_NO_IDEA", "OPENSSL_NO_JPAKE", "OPENSSL_NO_KRB5", "OPENSSL_NO_MD2", "OPENSSL_NO_MDC2", "OPENSSL_NO_OCB", "OPENSSL_NO_OCSP", "OPENSSL_NO_RC2", "OPENSSL_NO_RC5", "OPENSSL_NO_RFC3779", "OPENSSL_NO_RIPEMD", "OPENSSL_NO_RMD160", "OPENSSL_NO_SCTP", "OPENSSL_NO_SEED", "OPENSSL_NO_SM2", "OPENSSL_NO_SM3", "OPENSSL_NO_SM4", "OPENSSL_NO_SRP", "OPENSSL_NO_SSL_TRACE", "OPENSSL_NO_SSL2", "OPENSSL_NO_SSL3", "OPENSSL_NO_SSL3_METHOD", "OPENSSL_NO_STATIC_ENGINE", "OPENSSL_NO_STORE", "OPENSSL_NO_WHIRLPOOL", ]; fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let src_dir = Path::new(&crate_dir); let boringssl_src_dir = src_dir.join("third_party").join("boringssl"); let include_dir = boringssl_src_dir.join("src").join("include"); let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); let bindgen_file = out_dir.join("bindgen.rs"); let wrapper_header_src = src_dir.join("wrapper.h"); let wrapper_header_dst = out_dir.join("wrapper.h"); std::fs::copy(wrapper_header_src, wrapper_header_dst).unwrap(); let wrapper_source = out_dir.join("wrapper.c"); let target = env::var("TARGET").unwrap(); #[cfg(not(windows))] link_cxx_runtime(); // bindgen let binding = bindgen::Builder::default() .header("wrapper.h") .derive_default(false) .enable_function_attribute_detection() .wrap_static_fns(true) .wrap_static_fns_path(&wrapper_source) .use_core() .default_macro_constant_type(MacroTypeVariation::Signed) .rustified_enum("point_conversion_form_t") .allowlist_file(".*[[:punct:]]include[[:punct:]]openssl[[:punct:]].*\\.h") .clang_args([ format!("-I{}", include_dir.display()), format!("--target={target}"), ]) .generate() .expect("unable to generate binding for BoringSSL"); binding .write_to_file(&bindgen_file) .expect("failed to write bindgen file"); println!("cargo:rerun-if-changed=wrapper.c"); println!("cargo:rerun-if-changed=wrapper.h"); cc::Build::new() .cargo_metadata(true) .include(&include_dir) .file(wrapper_source) .compile("rustc_wrapper"); // build BoringSSL code println!("cargo:rerun-if-changed={}", boringssl_src_dir.display()); let mut cmake_config = cmake::Config::new(boringssl_src_dir); cmake_config.build_target("crypto").build_target("ssl"); #[cfg(windows)] cmake_config.generator("Ninja"); #[cfg(target_env = "msvc")] select_msvc_crt(&mut cmake_config); let boringssl_build_dir = cmake_config.build(); let lib_search_dir = Path::new(&boringssl_build_dir).join("build"); // set link options println!( "cargo:rustc-link-search=native={}", lib_search_dir.display() ); println!("cargo:rustc-link-lib=static=crypto"); println!("cargo:rustc-link-lib=static=ssl"); // OSSL CONF println!("cargo:conf={}", OSSL_CONF_DEFINES.join(",")); } #[cfg(not(windows))] fn link_cxx_runtime() { // libssl requires a C++ runtime, such as libstdc++ or libc++ println!("cargo:rerun-if-changed=link_runtime.cpp"); cc::Build::new() .cargo_metadata(true) .cpp(true) .file("link_runtime.cpp") .compile("link_runtime"); } #[cfg(target_env = "msvc")] fn select_msvc_crt(cmake_config: &mut cmake::Config) { let linkage = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or_default(); if linkage.contains("crt-static") { cmake_config.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded"); } else { cmake_config.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreadedDLL"); } }