use std::{ env::{temp_dir, var}, fs::copy, path::{Path, PathBuf}, process::Command, }; fn find_target_dir(out_dir: &Path) -> Option { for ancestor in out_dir.ancestors() { let read_dir = ancestor .read_dir() .expect(&format!("can not read dir for {}", ancestor.display())); for entry in read_dir { if let Ok(f) = entry { if f.file_name() == ".cargo-lock" { return Some(ancestor.to_path_buf()); } } } } None } const INTER_MEM_NAME: &str = "libinter_mem.so"; fn main() { println!("cargo:rerun-if-changed=mem"); if !Path::new("mem").exists() { return; } let out_dir = var("OUT_DIR").expect("env OUT_DIR not found"); let out_dir = Path::new(&out_dir); let target_dir = find_target_dir(out_dir).expect("can not found target dir"); let temp_dir = temp_dir() .join(INTER_MEM_NAME) .join("target") .to_string_lossy() .to_string(); let target = var("TARGET").expect("env TARGET not found"); let profile = var("PROFILE").expect("env PROFILE not found"); let mut result_dir = Path::new(&temp_dir).join(&target); let mut cmd = Command::new("cargo"); cmd.current_dir("mem") .args(["build", "--target", &target, "--target-dir", &temp_dir]); result_dir = if profile != "debug" { cmd.arg(format!("--{profile}")); result_dir.join(profile) } else { result_dir.join("debug") }; let output = cmd.output().unwrap(); if !output.status.success() { panic!( "intercept generate {} error:\n{}", INTER_MEM_NAME, String::from_utf8_lossy(&output.stderr) ); } copy( result_dir.join(INTER_MEM_NAME), target_dir.join(INTER_MEM_NAME), ) .expect(&format!("copy result {} error", INTER_MEM_NAME)); }