Skip to main content

upstream_rs/services/builder/profiles/
zig.rs

1use 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}