use std::{env, fs, path::PathBuf, process::Command}; fn run_pnpm(args: &[&str], cwd: &str) { let mut cmd = if cfg!(target_os = "windows") { let mut c = Command::new("cmd"); c.args(["/C", "pnpm"]); c } else { Command::new("pnpm") }; let status = cmd .args(args) .current_dir(cwd) .status() .expect("failed to run pnpm"); if !status.success() { panic!("pnpm command failed: {:?}", args); } } fn find_all_file(path: PathBuf) -> Vec { let mut files = vec![]; for entry in fs::read_dir(path).unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.is_file() { files.push(path); } else if path.is_dir() { files.extend(find_all_file(path)); } } files } fn main() { println!("cargo:rerun-if-changed=../../package.json"); println!("cargo:rerun-if-changed=../../pnpm-lock.yaml"); println!("cargo:rerun-if-changed=../../tsconfig.json"); println!("cargo:rerun-if-changed=../../src/"); let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let project_root = manifest_dir.parent().unwrap().parent().unwrap(); let node_modules = project_root.join("node_modules"); let _cache_file = node_modules.join(".cache_hash"); // Build frontend using pnpm in project root println!("cargo:warning=Building frontend..."); run_pnpm(&["run", "build"], project_root.to_str().unwrap()); // Embed dist/ into OUT_DIR as blob files + generated .rs let dist = project_root.join("dist"); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let blob_dir = out_dir.join("dist_blobs"); fs::create_dir_all(&blob_dir).unwrap(); let mut strs = vec![]; for file in find_all_file(dist.clone()) { let key = file.strip_prefix(&dist).unwrap() .components() .collect::() .to_string_lossy() .replace('\\', "/"); let safe_name = key.replace('/', "_").replace('\\', "_"); let blob_path = blob_dir.join(&safe_name); fs::copy(&file, &blob_path).unwrap(); let key_literal = format!("\"{}\"", key.replace('"', "\\\"")); strs.push(format!(" ({}, include_bytes!(\"dist_blobs/{}\")),", key_literal, safe_name)); } let out_file = out_dir.join("frontend.rs"); let content = format!( "lazy_static::lazy_static! {{\n pub static ref FRONTEND: Vec<(&'static str, &'static [u8])> = vec![\n{} ];\n}}\n", strs.join("\n") ); fs::write(&out_file, content).unwrap(); println!("cargo:include={}", out_file.display()); }