use std::{error::Error, io::Write, path::PathBuf}; fn main() -> Result<(), Box> { build_linux_setup_header()?; Ok(()) } fn build_linux_setup_header() -> Result<(), Box> { // Build the setup header to raw binary. let source_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let setup_crate_dir = source_dir .join("src") .join("arch") .join("x86") .join("boot") .join("linux_boot") .join("setup"); let target_json = setup_crate_dir.join("x86_64-i386_protected_mode.json"); println!( "cargo:rerun-if-changed={}", setup_crate_dir.to_str().unwrap() ); let cargo = std::env::var("CARGO").unwrap(); let mut cmd = std::process::Command::new(cargo); cmd.arg("install").arg("jinux-frame-x86-boot-setup"); cmd.arg("--locked"); cmd.arg("--path").arg(setup_crate_dir.to_str().unwrap()); cmd.arg("--target").arg(target_json.as_os_str()); cmd.arg("-Zbuild-std=core,compiler_builtins"); cmd.arg("-Zbuild-std-features=compiler-builtins-mem"); cmd.arg("--root").arg(out_dir.as_os_str()); cmd.env_remove("RUSTFLAGS"); cmd.env_remove("CARGO_ENCODED_RUSTFLAGS"); let output = cmd.output()?; if !output.status.success() { std::io::stdout().write_all(&output.stdout).unwrap(); std::io::stderr().write_all(&output.stderr).unwrap(); return Err(format!( "Failed to build linux x86 setup header::\n\tcommand `{:?}`\n\treturned {}", cmd, output.status ) .into()); } // Strip the elf header to get the raw header. let elf_path = out_dir.join("bin").join("jinux-frame-x86-boot-setup"); let bin_path = out_dir.join("bin").join("jinux-frame-x86-boot-setup.bin"); let objcopy = std::env::var("OBJCOPY").unwrap(); let mut cmd = std::process::Command::new(objcopy); cmd.arg("-O").arg("binary"); cmd.arg("-j").arg(".header"); cmd.arg("-j").arg(".text"); cmd.arg("-j").arg(".rodata"); cmd.arg("-j").arg(".data"); cmd.arg("-j").arg(".bss"); cmd.arg("-j").arg(".eh_frame"); cmd.arg("-j").arg(".eh_frame_hdr"); cmd.arg(elf_path.to_str().unwrap()); cmd.arg(bin_path.to_str().unwrap()); let output = cmd.output()?; if !output.status.success() { std::io::stdout().write_all(&output.stdout).unwrap(); std::io::stderr().write_all(&output.stderr).unwrap(); return Err(format!( "Failed to strip linux boot header:\n\tcommand `{:?}`\n\treturned {}", cmd, output.status ) .into()); } Ok(()) }