use std::{ env, io::{self, Write}, path::{Path, PathBuf}, process, }; fn main() { println!("cargo::rustc-check-cfg=cfg(web_sys_unstable_apis)"); println!("cargo:rerun-if-changed=uno.config.ts"); println!("cargo:rerun-if-changed=package.json"); println!("cargo:rerun-if-changed=tailwind.config.js"); // Routes are embedded by the shared crate's build process // Skip CSS build in development mode if SKIP_CSS_BUILD is set or if package.json not found if env::var("SKIP_CSS_BUILD").is_ok() { println!("cargo:warning=Skipping CSS build due to SKIP_CSS_BUILD environment variable"); return; } // Check if we're in a framework-only context (no package.json available) let package_json_paths = ["../package.json", "package.json", "../../package.json", "../../../package.json", "../../../../package.json"]; let has_package_json = package_json_paths .iter() .any(|path| Path::new(path).exists()); if !has_package_json { println!("cargo:warning=No package.json found - assuming framework-only build, skipping CSS processing"); return; } // Check if node_modules exists in various locations, if not run pnpm install let node_modules_paths = ["../node_modules", "node_modules", "../../node_modules"]; let node_modules_exists = node_modules_paths .iter() .any(|path| Path::new(path).exists()); if !node_modules_exists { println!("cargo:warning=node_modules not found, running pnpm install..."); // Try to find package.json to determine correct directory let package_json_paths = ["../package.json", "package.json", "../../package.json", "../../../package.json", "../../../../package.json"]; let install_dir = package_json_paths .iter() .find(|path| Path::new(path).exists()) .map(|path| Path::new(path).parent().unwrap_or(Path::new("."))) .unwrap_or(Path::new("..")); match process::Command::new("pnpm") .arg("install") .current_dir(install_dir) .output() { Ok(output) => { if !output.status.success() { let _ = io::stdout().write_all(&output.stdout); let _ = io::stdout().write_all(&output.stderr); panic!("pnpm install failed"); } println!("cargo:warning=pnpm install completed successfully"); } Err(e) => { println!("cargo:warning=Failed to run pnpm install: {e:?}"); println!("cargo:warning=Please run 'pnpm install' manually in the project root"); // Don't panic here, just warn - the build might still work } } } // Use build coordinator for CSS build to prevent duplication let css_output_path = PathBuf::from("public/website.css"); let css_sources = vec![ PathBuf::from("uno.config.ts"), PathBuf::from("package.json"), PathBuf::from("tailwind.config.js"), ]; // Try to use the build coordinator, fall back to direct build if it fails match coordinate_css_build(&css_output_path, &css_sources) { Ok(built) => { if built { println!("cargo:warning=CSS build completed successfully via coordinator"); } else { println!("cargo:warning=CSS build skipped - already up to date"); } } Err(e) => { println!("cargo:warning=Build coordinator failed: {}, falling back to direct build", e); run_direct_css_build(); } } } /// Coordinate CSS build using the build coordinator from tools crate fn coordinate_css_build(output_path: &Path, source_paths: &[PathBuf]) -> Result { // Since tools crate may not be available during client build, we'll implement // a simple coordinator check here instead of importing tools use std::fs; // Simple freshness check without full coordinator if output_path.exists() { let output_meta = fs::metadata(output_path).map_err(|e| e.to_string())?; let output_modified = output_meta.modified().map_err(|e| e.to_string())?; let mut needs_rebuild = false; for source_path in source_paths { if source_path.exists() { let source_meta = fs::metadata(source_path).map_err(|e| e.to_string())?; let source_modified = source_meta.modified().map_err(|e| e.to_string())?; if source_modified > output_modified { needs_rebuild = true; break; } } } if !needs_rebuild { return Ok(false); // No rebuild needed } } // Need to build - run the CSS build run_direct_css_build(); Ok(true) } /// Run direct CSS build without coordinator fn run_direct_css_build() { match process::Command::new("sh") .arg("-c") .arg("pnpm run build") .output() { Ok(output) => { if !output.status.success() { let _ = io::stdout().write_all(&output.stdout); let _ = io::stdout().write_all(&output.stderr); panic!("UnoCSS error"); } } Err(e) => panic!("UnoCSS error: {e:?}"), }; }