use sha2::{Digest, Sha256}; use std::env; use std::fs; use std::path::PathBuf; fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let src_dir = PathBuf::from(&manifest_dir).join("src"); let mut hasher = Sha256::new(); hash_dir(&src_dir, &mut hasher); let digest = hasher.finalize(); let hash_hex = format!("{:x}", digest); println!("cargo:rustc-env=BUILD_SRC_HASH={}", hash_hex); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); fs::write(out_dir.join("build_hash.txt"), format!("{}\n", hash_hex)).unwrap(); // 嵌入 RSA 公钥(用于 selfhosted 验签) let pubkey_path = PathBuf::from(&manifest_dir).join("embedded").join("pubkey.pem"); if let Ok(pubkey) = fs::read_to_string(&pubkey_path) { let trimmed = pubkey.trim(); if !trimmed.is_empty() { println!("cargo:rustc-env=CRAFTLABS_SELFHOSTED_PUBKEY={}", trimmed); } } println!("cargo:rerun-if-changed=embedded/pubkey.pem"); } fn hash_dir(dir: &PathBuf, hasher: &mut Sha256) { if let Ok(entries) = fs::read_dir(dir) { let mut paths: Vec<_> = entries.filter_map(|e| e.ok()).collect(); paths.sort_by_key(|e| e.file_name()); for entry in paths { let path = entry.path(); if path.is_dir() { hash_dir(&path, hasher); } else if path.extension().map_or(false, |ext| ext == "rs") { if let Ok(content) = fs::read(&path) { hasher.update(&content); } } } } }