Files
bichon/crates/server/build.rs
T

114 lines
3.7 KiB
Rust

use std::{io::Result, process::Command};
fn main() -> Result<()> {
if cfg!(target_os = "windows") {
println!("cargo:rustc-link-lib=Rstrtmgr");
}
let output = Command::new("git")
.args(["rev-parse", "--short", "HEAD"])
.output()
.expect("Failed to get git commit hash");
let git_hash = String::from_utf8(output.stdout)
.expect("Invalid UTF-8")
.trim()
.to_string();
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
// Build frontend assets
build_frontend();
Ok(())
}
fn build_frontend() {
let web_dir = std::path::Path::new("../../web");
let dist_dir = web_dir.join("dist");
// Re-run build.rs when frontend source or dependencies change.
println!("cargo:rerun-if-changed=../../web/package.json");
println!("cargo:rerun-if-changed=../../web/pnpm-lock.yaml");
println!("cargo:rerun-if-changed=../../web/tsconfig.json");
println!("cargo:rerun-if-changed=../../web/vite.config.ts");
println!("cargo:rerun-if-changed=../../web/index.html");
println!("cargo:rerun-if-changed=../../web/src/");
// Find a working pnpm command. On Windows it may only be available
// via cmd.exe (PATH set by the installer, not inherited by bash).
let mut pnpm_cmd = None;
for candidate in &["pnpm", "pnpm.cmd"] {
if command_ok(candidate, &["--version"], web_dir) {
pnpm_cmd = Some(*candidate);
break;
}
}
// Windows fallback: run through cmd.exe which has the full system PATH.
if pnpm_cmd.is_none() && cfg!(target_os = "windows") {
if command_ok("cmd", &["/c", "pnpm.cmd", "--version"], web_dir) {
pnpm_cmd = Some("cmd");
}
}
let Some(cmd) = pnpm_cmd else {
// If dist/ already exists (built manually), allow the build to proceed.
if dist_dir.exists() {
eprintln!(
"WARNING: `pnpm` not found in PATH but `web/dist/` exists.\n\
The embedded frontend may be stale. Install pnpm and run\n\
`cd web && pnpm run build` to update it.\n"
);
return;
}
eprintln!(
"\nERROR: `pnpm` not found. Install Node.js and pnpm, then run:\n\
cd web && pnpm install && pnpm run build\n"
);
std::process::exit(1);
};
if !web_dir.join("node_modules").exists() {
// Fresh clone — install dependencies first.
eprintln!("Installing frontend dependencies (one-time setup)...");
if !run_pnpm(cmd, &["install"], web_dir) {
eprintln!("\nERROR: `pnpm install` failed. See output above.\n");
std::process::exit(1);
}
}
if !run_pnpm(cmd, &["run", "build"], web_dir) {
eprintln!("\nERROR: `pnpm run build` failed. See output above.\n");
std::process::exit(1);
}
}
fn command_ok(cmd: &str, args: &[&str], dir: &std::path::Path) -> bool {
Command::new(cmd)
.args(args)
.current_dir(dir)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
fn run_pnpm(cmd: &str, args: &[&str], dir: &std::path::Path) -> bool {
if cmd == "cmd" {
let mut full_args = vec!["/c", "pnpm.cmd"];
full_args.extend_from_slice(args);
Command::new("cmd")
.args(&full_args)
.current_dir(dir)
.status()
.map(|s| s.success())
.unwrap_or(false)
} else {
Command::new(cmd)
.args(args)
.current_dir(dir)
.status()
.map(|s| s.success())
.unwrap_or(false)
}
}