mirror of
https://github.com/geoffsee/predict-otron-9001.git
synced 2025-09-08 22:46:44 +00:00
reorg + update docs with new paths
This commit is contained in:
204
integration/cli/build.rs
Normal file
204
integration/cli/build.rs
Normal file
@@ -0,0 +1,204 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, BufRead, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{ChildStderr, ChildStdout, Command, Stdio};
|
||||
use std::thread;
|
||||
use std::time::{Duration, SystemTime};
|
||||
mod bun_target;
|
||||
use bun_target::BunTarget;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=");
|
||||
|
||||
if let Err(e) = run_build() {
|
||||
println!("cargo:warning=build.rs failed: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_build() -> io::Result<()> {
|
||||
let manifest_dir =
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
|
||||
let package_dir = manifest_dir.join("package");
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set by Cargo"));
|
||||
let output_path = out_dir.join("client-cli");
|
||||
|
||||
let bun_tgt = BunTarget::from_cargo_env()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
|
||||
|
||||
// Optional: warn if using a Bun target that’s marked unsupported in your chart
|
||||
if matches!(bun_tgt, BunTarget::WindowsArm64) {
|
||||
println!(
|
||||
"cargo:warning=bun-windows-arm64 is marked unsupported in the compatibility chart"
|
||||
);
|
||||
}
|
||||
|
||||
warn(&format!("Building CLI into: {}", output_path.display()));
|
||||
|
||||
// --- bun install (in ./package), keep temps inside OUT_DIR ---
|
||||
let mut install = Command::new("bun")
|
||||
.current_dir(&package_dir)
|
||||
.env("TMPDIR", &out_dir)
|
||||
.arg("install")
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| io::Error::new(e.kind(), format!("Failed to spawn `bun install`: {e}")))?;
|
||||
|
||||
let install_join = stream_child("bun install", install.stdout.take(), install.stderr.take());
|
||||
let install_status = install.wait()?;
|
||||
// ensure streams finish
|
||||
join_streams(install_join);
|
||||
|
||||
if !install_status.success() {
|
||||
let code = install_status.code().unwrap_or(1);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("bun install failed with status {code}"),
|
||||
));
|
||||
}
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
// --- bun build (in ./package), emit to OUT_DIR, keep temps inside OUT_DIR ---
|
||||
let mut build = Command::new("bun")
|
||||
.current_dir(&package_dir)
|
||||
.env("TMPDIR", &out_dir)
|
||||
.arg("build")
|
||||
.arg("./cli.ts")
|
||||
.arg(format!("--target={}", bun_tgt.as_bun_flag()))
|
||||
.arg("--compile")
|
||||
.arg("--outfile")
|
||||
.arg(&output_path)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| io::Error::new(e.kind(), format!("Failed to spawn `bun build`: {e}")))?;
|
||||
|
||||
let build_join = stream_child("bun build", build.stdout.take(), build.stderr.take());
|
||||
let status = build.wait()?;
|
||||
// ensure streams finish
|
||||
join_streams(build_join);
|
||||
|
||||
if status.success() {
|
||||
info("bun build succeeded");
|
||||
} else {
|
||||
let code = status.code().unwrap_or(1);
|
||||
warn(&format!("bun build failed with status: {code}"));
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "bun build failed"));
|
||||
}
|
||||
|
||||
// Ensure the output is executable (after it exists)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perms = fs::metadata(&output_path)?.permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(&output_path, perms)?;
|
||||
}
|
||||
|
||||
println!("cargo:warning=Built CLI at {}", output_path.display());
|
||||
println!("cargo:rustc-env=CLIENT_CLI_BIN={}", output_path.display());
|
||||
|
||||
// --- Cleanup stray .bun-build temp files (conservative: older than 5 minutes) ---
|
||||
for dir in [&manifest_dir, &package_dir, &out_dir] {
|
||||
if let Err(e) = remove_bun_temp_files(dir, Some(Duration::from_secs(5 * 60))) {
|
||||
println!("cargo:warning=cleanup in {} failed: {e}", dir.display());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Spawn readers for child's stdout/stderr so we don't deadlock on pipe buffers
|
||||
fn stream_child(
|
||||
tag: &str,
|
||||
stdout: Option<ChildStdout>,
|
||||
stderr: Option<ChildStderr>,
|
||||
) -> (
|
||||
Option<thread::JoinHandle<()>>,
|
||||
Option<thread::JoinHandle<()>>,
|
||||
) {
|
||||
let t1 = stdout.map(|out| {
|
||||
let tag = tag.to_string();
|
||||
thread::spawn(move || {
|
||||
let reader = io::BufReader::new(out);
|
||||
for line in reader.lines() {
|
||||
info(&format!("[{tag} stdout] {}", line.unwrap_or_default()));
|
||||
}
|
||||
})
|
||||
});
|
||||
let t2 = stderr.map(|err| {
|
||||
let tag = tag.to_string();
|
||||
thread::spawn(move || {
|
||||
let reader = io::BufReader::new(err);
|
||||
for line in reader.lines() {
|
||||
warn(&format!("[{tag} stderr] {}", line.unwrap_or_default()));
|
||||
}
|
||||
})
|
||||
});
|
||||
(t1, t2)
|
||||
}
|
||||
|
||||
fn join_streams(
|
||||
joins: (
|
||||
Option<thread::JoinHandle<()>>,
|
||||
Option<thread::JoinHandle<()>>,
|
||||
),
|
||||
) {
|
||||
if let Some(j) = joins.0 {
|
||||
let _ = j.join();
|
||||
}
|
||||
if let Some(j) = joins.1 {
|
||||
let _ = j.join();
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_bun_temp_files(dir: &Path, older_than: Option<Duration>) -> io::Result<()> {
|
||||
let now = SystemTime::now();
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Files like ".1860e7df40ff1bef-00000000.bun-build"
|
||||
let name = entry.file_name();
|
||||
let name = name.to_string_lossy();
|
||||
let looks_like_bun_temp = name.starts_with('.') && name.ends_with(".bun-build");
|
||||
|
||||
if !looks_like_bun_temp {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(age) = older_than {
|
||||
if let Ok(meta) = entry.metadata() {
|
||||
if let Ok(modified) = meta.modified() {
|
||||
if now.duration_since(modified).unwrap_or_default() < age {
|
||||
// too new; skip to avoid racing an in-flight builder
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match fs::remove_file(&path) {
|
||||
Ok(_) => println!("cargo:warning=removed stray bun temp {}", path.display()),
|
||||
Err(e) => println!("cargo:warning=failed to remove {}: {e}", path.display()),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn warn(msg: &str) {
|
||||
let _ = writeln!(io::stderr(), "[build.rs] {msg}");
|
||||
println!("cargo:warning={msg}");
|
||||
}
|
||||
|
||||
fn info(msg: &str) {
|
||||
let _ = writeln!(io::stderr(), "[build.rs] {msg}");
|
||||
println!("cargo:warning=INFO|{msg}");
|
||||
}
|
Reference in New Issue
Block a user