use std::{env, path::Path};
macro_rules! svec {
($($x:expr),*$(,)?) => (vec![$($x.to_string()),*]);
}
fn append_simd128_flags(flags: &mut Vec<String>) {
flags.push("-mavx".to_string());
}
fn append_simd256_flags(flags: &mut Vec<String>) {
flags.push("-mavx2".to_string());
}
#[cfg(feature = "bindings")]
fn create_bindings(platform: Platform, home_dir: &Path) {
let jazz_dir = home_dir.join("jazz");
let mut clang_args = vec![format!("-I{}", jazz_dir.join("include").display())];
if platform.simd128 {
append_simd128_flags(&mut clang_args);
clang_args.push("-DSIMD128".to_string());
}
if platform.simd256 {
append_simd256_flags(&mut clang_args);
clang_args.push("-DSIMD256".to_string());
}
let bindings = bindgen::Builder::default()
.header("jazz/include/libjade.h")
.clang_args(clang_args)
.allowlist_function("jade_hash_.*")
.allowlist_var("JADE_HASH_.*")
.allowlist_function("jade_scalarmult_curve25519_.*")
.allowlist_var("JADE_SCALARMULT_CURVE25519_.*")
.allowlist_function("jade_hash_sha3_.*")
.allowlist_var("JADE_HASH_SHA3_.*")
.allowlist_function("jade_onetimeauth_poly1305_.*")
.allowlist_var("JADE_ONETIMEAUTH_POLY1305_.*")
.allowlist_function("jade_stream_chacha_chacha20.*")
.allowlist_var("JADE_STREAM_CHACHA_CHACHA20_.*")
.allowlist_function("jade_kem_kyber_kyber768_.*")
.allowlist_var("JADE_KEM_KYBER_KYBER768_.*")
.blocklist_type("__.*")
.layout_tests(false)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.use_core()
.generate()
.expect("Unable to generate bindings");
let home_bindings = home_dir.join("src/bindings.rs");
bindings
.write_to_file(home_bindings)
.expect("Couldn't write bindings!");
}
fn compile_files(library_name: &str, files: &[String], home_path: &Path, args: &[String]) {
let jazz_dir = home_path.join("jazz");
let mut build = cc::Build::new();
build
.files(files.iter().map(|fname| jazz_dir.join(fname)))
.warnings_into_errors(true)
.no_default_flags(true);
build.include(jazz_dir.join("include"));
build.opt_level(3);
for arg in args {
build.flag(arg);
}
build.compile(library_name);
}
fn build(platform: Platform, home_path: &Path) {
let args = Vec::new();
let files = svec![
"sha256.s",
"x25519_ref.s",
"x25519_mulx.s",
"sha3_224_ref.s",
"sha3_256_ref.s",
"sha3_384_ref.s",
"sha3_512_ref.s",
"chacha20_ref.s",
"poly1305_ref.s",
"kyber_kyber768_ref.s",
];
compile_files("jade", &files, home_path, &args);
if platform.simd256 {
let files256 = svec![
"sha3_224_avx2.s",
"sha3_256_avx2.s",
"sha3_384_avx2.s",
"sha3_512_avx2.s",
"chacha20_avx2.s",
"poly1305_avx2.s",
];
let mut simd256_flags = args.clone();
append_simd256_flags(&mut simd256_flags);
compile_files("jade_256", &files256, home_path, &simd256_flags);
}
if platform.simd128 {
let files128 = svec!["chacha20_avx.s", "poly1305_avx.s",];
let mut simd128_flags = args.clone();
append_simd128_flags(&mut simd128_flags);
compile_files("jade_128", &files128, home_path, &simd128_flags);
}
}
#[derive(Debug, Clone, Copy)]
struct Platform {
simd128: bool,
simd256: bool,
}
pub fn main() {
let home_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let home_path = Path::new(&home_dir);
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
let platform = if target != host {
Platform {
simd128: true,
simd256: true,
}
} else {
Platform {
simd128: libcrux_platform::simd128_support(),
simd256: libcrux_platform::simd256_support(),
}
};
build(platform, home_path);
println!("cargo:rerun-if-changed=jazz");
#[cfg(feature = "bindings")]
create_bindings(platform, home_path);
}