use std::{env, path::PathBuf, process::Command}; fn main() { let target = env::var("TARGET").unwrap(); if target != "x86_64-unknown-uefi" { return; } let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let lwext4_dir = manifest_dir.join("third_party/lwext4"); let config_dir = manifest_dir.join("third_party/lwext4_config/include/generated"); let shim = manifest_dir.join("src/fs/lwext4_shim.c"); println!("cargo:rerun-if-changed={}", shim.display()); println!( "cargo:rerun-if-changed={}", lwext4_dir.join("src").display() ); println!( "cargo:rerun-if-changed={}", manifest_dir .join("third_party/lwext4_config/include/generated/ext4_config.h") .display() ); let sources = [ "ext4.c", "ext4_balloc.c", "ext4_bitmap.c", "ext4_bcache.c", "ext4_block_group.c", "ext4_blockdev.c", "ext4_crc32.c", "ext4_debug.c", "ext4_dir.c", "ext4_dir_idx.c", "ext4_extent.c", "ext4_fs.c", "ext4_hash.c", "ext4_ialloc.c", "ext4_inode.c", "ext4_journal.c", "ext4_mbr.c", "ext4_super.c", "ext4_trans.c", "ext4_xattr.c", ]; let clang = env::var("CLANG").unwrap_or_else(|_| "clang".to_string()); let ar = env::var("AR").unwrap_or_else(|_| "llvm-ar".to_string()); let mut objects = Vec::new(); for source in sources { let input = lwext4_dir.join("src").join(source); let output = out_dir.join(format!("{source}.obj")); compile_c(&clang, &input, &output, &lwext4_dir, &config_dir); objects.push(output); } let shim_obj = out_dir.join("zeroos_lwext4_shim.obj"); compile_c(&clang, &shim, &shim_obj, &lwext4_dir, &config_dir); objects.push(shim_obj); let lib = out_dir.join("libzeroos_lwext4.a"); let status = Command::new(&ar) .arg("crs") .arg(&lib) .args(&objects) .status() .unwrap_or_else(|error| panic!("failed to run {ar}: {error}")); assert!(status.success(), "{ar} failed while archiving lwext4"); println!("cargo:rustc-link-search=native={}", out_dir.display()); println!("cargo:rustc-link-lib=static=zeroos_lwext4"); } fn compile_c( clang: &str, input: &PathBuf, output: &PathBuf, lwext4_dir: &PathBuf, config_dir: &PathBuf, ) { let status = Command::new(clang) .arg("-target") .arg("x86_64-unknown-windows") .arg("-ffreestanding") .arg("-fno-stack-protector") .arg("-fno-builtin") .arg("-mno-red-zone") .arg("-O2") .arg("-Wall") .arg("-Wno-unused-parameter") .arg("-Wno-missing-braces") .arg("-DCONFIG_USE_DEFAULT_CFG=0") .arg("-I") .arg(lwext4_dir.join("include")) .arg("-I") .arg(config_dir.parent().unwrap()) .arg("-c") .arg(input) .arg("-o") .arg(output) .status() .unwrap_or_else(|error| panic!("failed to run {clang}: {error}")); assert!( status.success(), "{clang} failed while compiling {}", input.display() ); }