use std::{env, fs, path::Path}; use abi_generator::{ abi::{ty::TypeWidth, AbiBuilder}, syntax::UnwrapFancy, TargetEnv, }; fn add_file<'a>(build: &'a mut cc::Build, name: &'a str) -> &'a mut cc::Build { println!("cargo:rerun-if-changed={}", name); build.file(name) } fn load_abi_definitions>(path: P) -> String { let mut content = String::new(); for file in fs::read_dir(path).unwrap() { let file = file.unwrap(); if file.path().extension().map(|x| x == "abi").unwrap_or(false) { println!("cargo:rerun-if-changed={}", file.path().display()); content.extend(fs::read_to_string(file.path())); } } content } fn build_libm() { println!("cargo:rerun-if-changed=libm/private.h"); let mut build = cc::Build::new(); build .compiler("clang") .flag("-ffreestanding") .flag("-nostdlib"); add_file(&mut build, "libm/s_truncf.c"); add_file(&mut build, "libm/s_ceilf.c"); add_file(&mut build, "libm/s_floorf.c"); add_file(&mut build, "libm/s_fabsf.c"); add_file(&mut build, "libm/s_scalbnf.c"); add_file(&mut build, "libm/s_copysignf.c"); add_file(&mut build, "libm/e_powf.c"); add_file(&mut build, "libm/e_sqrtf.c"); add_file(&mut build, "libm/e_hypotf.c"); add_file(&mut build, "libm/e_fmodf.c"); add_file(&mut build, "libm/w_powf.c"); add_file(&mut build, "libm/w_hypotf.c"); add_file(&mut build, "libm/w_fmodf.c"); build.compile("m"); } fn generate_abi>(target_is_64bit: bool, abi_path: P) { let output_dir = std::env::var("OUT_DIR").expect("$OUT_DIR not set"); let generated_calls = Path::new(&output_dir).join("generated_calls.rs"); let target_env = if target_is_64bit { TargetEnv { thin_pointer_width: TypeWidth::U64, fat_pointer_width: TypeWidth::U128, } } else { TargetEnv { thin_pointer_width: TypeWidth::U32, fat_pointer_width: TypeWidth::U64, } }; let abi = load_abi_definitions(abi_path); let abi = AbiBuilder::from_string(&abi, target_env).unwrap_fancy(&abi); let calls = prettyplease::unparse( &abi.emit_file(false, true) .unwrap_fancy("Could not emit system calls"), ); fs::write(generated_calls, calls).unwrap(); } fn main() { let target_is_64bit = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "64"; println!("cargo:rustc-check-cfg=cfg(rust_analyzer)"); build_libm(); generate_abi(target_is_64bit, "../abi/def"); }