1use std::path::Path;
2
3use anyhow::{Context, Result};
4use tempfile::TempDir;
5use tracing::info;
6
7use crate::codegen::{generate_cargo_toml, generate_main_rs};
8use crate::config::BuildConfig;
9
10pub fn build(cfg: &BuildConfig, output_dir: &str) -> Result<()> {
11 let tmp = TempDir::new().context("create temp dir")?;
12 let tmp_path = tmp.path();
13
14 std::fs::create_dir_all(tmp_path.join("src"))?;
16 std::fs::write(tmp_path.join("Cargo.toml"), generate_cargo_toml(cfg))?;
17 std::fs::write(tmp_path.join("src/main.rs"), generate_main_rs(cfg))?;
18
19 info!(dir = %tmp_path.display(), "compiling custom binary");
20
21 let status = std::process::Command::new("cargo")
23 .args(["build", "--release"])
24 .current_dir(tmp_path)
25 .status()
26 .context("run cargo")?;
27
28 if !status.success() {
29 anyhow::bail!("cargo build failed with status {status}");
30 }
31
32 let binary_name = &cfg.build.output;
34 let src = tmp_path.join("target/release").join(binary_name);
35 let dst = Path::new(output_dir).join(binary_name);
36 std::fs::copy(&src, &dst)
37 .with_context(|| format!("copy {} → {}", src.display(), dst.display()))?;
38
39 info!(output = %dst.display(), "binary ready");
40 Ok(())
41}