use std::env; use std::path::Path; use std::process::Command; fn main() { println!("cargo:rerun-if-changed=client"); build_client(); let out_dir = env::var("OUT_DIR").unwrap(); setup_nyx(&out_dir); create_nyx_workdir(&out_dir); } #[track_caller] fn shell(cwd: impl AsRef, command_string: &str) { let cwd = cwd.as_ref(); let mut parts = command_string.split(" "); let command_name = parts.next().unwrap(); let mut command = Command::new(command_name); command.current_dir(cwd); command.stdout(std::process::Stdio::inherit()); command.stderr(std::process::Stdio::inherit()); command.args(parts); let mut process = command.spawn().unwrap(); let exit_status = process.wait().unwrap(); if !exit_status.success() { panic!( "Command failed with {exit_status}: {}> {command_string}", cwd.display() ); } } fn build_client() { shell("client", "cargo build --release"); } fn setup_nyx(out_dir: &str) { let packer_path = std::path::PathBuf::from(format!("{out_dir}/packer")); let qemu_path = std::path::PathBuf::from(format!("{out_dir}/QEMU-Nyx")); if !packer_path.exists() { shell(out_dir, "git clone https://github.com/nyx-fuzz/packer/"); } if !qemu_path.exists() { println!("cargo:warning=Cloning and building QEMU-Nyx. This may take a while..."); shell( out_dir, "git clone https://github.com/nyx-fuzz/QEMU-Nyx --depth 1", ); shell(qemu_path, "bash compile_qemu_nyx.sh full_static") } } fn create_nyx_workdir(out_dir: &str) { // Create the directory and move required binaries to it let repository_root = env::var("CARGO_MANIFEST_DIR").unwrap(); shell( out_dir, &format!( "python3 packer/packer/nyx_packer.py {repository_root}/target/release/client build afl processor_trace --fast_reload_mode --purge" ), ); // Create the nyx config shell( out_dir, "python3 packer/packer/nyx_config_gen.py build Kernel", ); // Pass the path to the build directory to src/main.rs println!("cargo:rustc-env=NYX_SHAREDIR={out_dir}/build") }