upstream_rs/services/builder/profiles/
zig.rs1use std::path::{Path, PathBuf};
2use std::process::Command;
3
4use anyhow::{Result, anyhow, bail};
5
6use crate::services::builder::{
7 BuildProfile,
8 profiles::{BuildProfileHandler, emit_line_callback, run_command_with_line_callback},
9};
10
11pub struct ZigProfile;
12
13impl ZigProfile {
14 fn binary_name(package_name: &str) -> String {
15 #[cfg(windows)]
16 {
17 format!("{package_name}.exe")
18 }
19 #[cfg(not(windows))]
20 {
21 package_name.to_string()
22 }
23 }
24
25 fn find_project_dir(workspace: &Path) -> Option<PathBuf> {
26 if workspace.join("build.zig").is_file() {
27 Some(workspace.to_path_buf())
28 } else {
29 None
30 }
31 }
32}
33
34impl BuildProfileHandler for ZigProfile {
35 fn profile(&self) -> BuildProfile {
36 BuildProfile::Zig
37 }
38
39 fn detect(&self, workspace: &Path) -> bool {
40 Self::find_project_dir(workspace).is_some()
41 }
42
43 fn run_build(
44 &self,
45 workspace: &Path,
46 package_name: &str,
47 line_callback: &mut Option<&mut dyn FnMut(&str)>,
48 ) -> Result<PathBuf> {
49 let project_dir = Self::find_project_dir(workspace).ok_or_else(|| {
50 anyhow!(
51 "Could not find build.zig in repository root '{}'.",
52 workspace.display()
53 )
54 })?;
55
56 emit_line_callback(
57 line_callback,
58 "Running zig build -Doptimize=ReleaseSafe ...",
59 );
60 let status = run_command_with_line_callback(
61 Command::new("zig")
62 .arg("build")
63 .arg("-Doptimize=ReleaseSafe")
64 .current_dir(&project_dir),
65 "Failed to run 'zig build -Doptimize=ReleaseSafe'. Is Zig installed?",
66 line_callback,
67 )?;
68
69 if !status.success() {
70 bail!("Zig build failed for '{}'", package_name);
71 }
72
73 let artifact = project_dir
74 .join("zig-out")
75 .join("bin")
76 .join(Self::binary_name(package_name));
77
78 if !artifact.exists() {
79 return Err(anyhow!(
80 "Zig build succeeded but artifact was not found at '{}'",
81 artifact.display()
82 ));
83 }
84
85 Ok(artifact)
86 }
87}