Files
yggdrasil/lib/runtime/build.rs
T
2026-03-28 01:58:09 +02:00

103 lines
3.2 KiB
Rust

use std::{env, fs, path::Path};
use abi_generator::{
TargetEnv,
abi::{AbiBuilder, ty::TypeWidth},
syntax::UnwrapFancy,
};
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<P: AsRef<Path>>(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();
let rust_target = env::var("TARGET").unwrap();
let cc_target = match rust_target.as_ref() {
"x86_64-unknown-none" | "x86_64-unknown-yggdrasil" => "x86_64-unknown-none",
"aarch64-unknown-none" | "aarch64-unknown-yggdrasil" => "aarch64-unknown-none",
"riscv64-unknown-yggdrasil" | "riscv64-unknown-none" => "riscv64-unknown-none",
_ => todo!("{rust_target:?}"),
};
build
.compiler("clang")
.flag("-ffreestanding")
.flag("-nostdlib");
if cc_target == "riscv64-unknown-none" {
build.flag("--target=riscv64-unknown-none");
} else {
build.target(cc_target);
}
add_file(&mut build, "libm/e_fmodf.c");
add_file(&mut build, "libm/e_hypotf.c");
add_file(&mut build, "libm/e_log.c");
add_file(&mut build, "libm/e_powf.c");
add_file(&mut build, "libm/e_sqrtf.c");
add_file(&mut build, "libm/s_ceilf.c");
add_file(&mut build, "libm/s_copysignf.c");
add_file(&mut build, "libm/s_fabsf.c");
add_file(&mut build, "libm/s_floorf.c");
add_file(&mut build, "libm/s_scalbnf.c");
add_file(&mut build, "libm/s_trunc.c");
add_file(&mut build, "libm/s_truncf.c");
add_file(&mut build, "libm/w_fmodf.c");
add_file(&mut build, "libm/w_hypotf.c");
add_file(&mut build, "libm/w_log.c");
add_file(&mut build, "libm/w_powf.c");
build.compile("m");
}
fn generate_abi<P: AsRef<Path>>(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");
}