use cc::Build;
use crate::{
config::{Arch, Configuration},
files::{
FileList,
Pattern::{Contains, End, Exact, Start},
DIST_C89, DIST_KARAMEL_INCLUDE, DIST_KARAMEL_MINIMAL_INCLUDE,
},
};
use std::{env, fs, path::Path};
#[derive(Debug)]
pub struct Make {
config: Configuration,
}
impl Make {
pub fn new(config: Configuration) -> Self {
Self { config }
}
pub fn build(&self) {
let out_dir = env::var("OUT_DIR").expect("Failed to get target output directory");
let config_h_path = Path::new(&out_dir).join("config.h");
let config_h = self.config_h();
fs::write(config_h_path, config_h).expect("Failed to create config.h");
let c_sources = dbg!(self.c_sources());
let asm_sources = dbg!(self.asm_sources());
let includes = self.includes();
Build::new()
.include(out_dir)
.includes(includes)
.files(c_sources.paths())
.files(asm_sources.paths())
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-variable")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-unused-function")
.flag_if_supported("-Wno-cpp")
.compile("evercrypt");
}
fn config_h(&self) -> String {
let target_arch = match self.config.arch {
Arch::arm if !self.config.v128 => "#define TARGET_ARCHITECTURE TARGET_ARCHITECTURE_ID_ARM7",
Arch::arm => "#define TARGET_ARCHITECTURE TARGET_ARCHITECTURE_ID_ARM8",
Arch::x86 => "#define TARGET_ARCHITECTURE TARGET_ARCHITECTURE_ID_X86",
Arch::x86_64 => "#define TARGET_ARCHITECTURE TARGET_ARCHITECTURE_ID_X64",
};
let intrinsics = match self.config.intrinsics {
true => "#define HACL_CAN_COMPILE_INTRINSICS 1",
false => "// #define HACL_CAN_COMPILE_INTRINSICS 1",
};
let vale = match self.config.vale {
true => "#define HACL_CAN_COMPILE_VALE 1",
false => "// #define HACL_CAN_COMPILE_VALE 1",
};
let inline_asm = match self.config.inline_asm {
true => "#define HACL_CAN_COMPILE_INLINE_ASM 1",
false => "// #define HACL_CAN_COMPILE_INLINE_ASM 1",
};
let v128 = match self.config.v128 {
true => "#define HACL_CAN_COMPILE_VEC128 1",
false => "#define Lib_IntVector_Intrinsics_vec128 void *",
};
let v256 = match self.config.v256 {
true => "#define HACL_CAN_COMPILE_VEC256 1",
false => "#define Lib_IntVector_Intrinsics_vec256 void *",
};
let native_u128 = match self.config.native_u128 {
true => "#define HACL_CAN_COMPILE_UINT128 1",
false => "// #define HACL_CAN_COMPILE_UINT128 1",
};
let header = format! {
r#"
{target_arch}
{intrinsics}
{vale}
{inline_asm}
{v128}
{v256}
{native_u128}
#define LINUX_NO_EXPLICIT_BZERO 1
"#
};
header.lines().map(|line| format!("{}\n", line.trim())).collect()
}
fn c_sources(&self) -> FileList {
let mut c_sources = FileList::new();
c_sources.add(DIST_C89, End(".c"));
if !self.config.vale {
c_sources.remove(Start("Hacl_HPKE_Curve64_") + End(".c"));
c_sources.remove(Exact("Hacl_Curve25519_64.c"));
c_sources.remove(Exact("evercrypt_vale_stubs.c"));
}
if !self.config.v128 {
c_sources.remove(Contains("CP128") + End(".c"));
c_sources.remove(End("_128.c"));
c_sources.remove(End("_Vec128.c"));
}
if !self.config.v256 {
c_sources.remove(Contains("CP256") + End(".c"));
c_sources.remove(End("_256.c"));
c_sources.remove(End("_Vec256.c"));
}
c_sources
}
fn asm_sources(&self) -> FileList {
let mut asm_sources = FileList::new();
if self.config.vale {
let arch = match self.config.arch {
Arch::x86_64 => "x86_64",
_ => return asm_sources,
};
let os = env::var("CARGO_CFG_TARGET_OS").expect("Cannot determine target OS");
let os_env = env::var("CARGO_CFG_TARGET_ENV").expect("Cannot determine target environment");
let (os, ext) = match os.as_str() {
"macos" | "ios" => ("darwin", "S"),
"linux" => ("linux", "S"),
"windows" => match os_env.as_str() {
"msvc" => ("msvc", "asm"),
"gnu" => ("linux", "S"),
_ => return asm_sources,
},
_ => return asm_sources,
};
let ext = format!("-{arch}-{os}.{ext}");
asm_sources.add(DIST_C89, End(ext));
}
asm_sources
}
fn includes(&self) -> &'static [&'static str] {
&[DIST_C89, DIST_KARAMEL_INCLUDE, DIST_KARAMEL_MINIMAL_INCLUDE]
}
}