Skip to main content

cargo_zigbuild/
rustc.rs

1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::{self, Command};
4
5use anyhow::{Context, Result};
6use clap::Parser;
7
8use crate::Zig;
9
10/// Compile a package, and pass extra options to the compiler
11/// with zig as the linker
12#[derive(Clone, Debug, Default, Parser)]
13#[command(
14    display_order = 1,
15    after_help = "Run `cargo help rustc` for more detailed information."
16)]
17pub struct Rustc {
18    /// Disable zig linker
19    #[arg(skip)]
20    pub disable_zig_linker: bool,
21
22    /// Enable zig ar
23    #[arg(skip)]
24    pub enable_zig_ar: bool,
25
26    /// Minimum macOS version, overrides `MACOSX_DEPLOYMENT_TARGET`
27    #[arg(skip)]
28    pub macosx_deployment_target: Option<String>,
29
30    #[command(flatten)]
31    pub cargo: cargo_options::Rustc,
32}
33
34impl Rustc {
35    /// Create a new build from manifest path
36    #[allow(clippy::field_reassign_with_default)]
37    pub fn new(manifest_path: Option<PathBuf>) -> Self {
38        let mut build = Self::default();
39        build.manifest_path = manifest_path;
40        build
41    }
42
43    /// Execute `cargo rustc` command with zig as the linker
44    pub fn execute(&self) -> Result<()> {
45        let mut rustc = self.build_command()?;
46
47        let mut child = rustc.spawn().context("Failed to run cargo rustc")?;
48        let status = child.wait().expect("Failed to wait on cargo build process");
49        if !status.success() {
50            process::exit(status.code().unwrap_or(1));
51        }
52        Ok(())
53    }
54
55    /// Generate cargo subcommand
56    pub fn build_command(&self) -> Result<Command> {
57        let mut build = self.cargo.command();
58        if !self.disable_zig_linker {
59            Zig::apply_command_env(
60                self.manifest_path.as_deref(),
61                self.release,
62                &self.cargo.common,
63                &mut build,
64                self.enable_zig_ar,
65                self.macosx_deployment_target.as_deref(),
66            )?;
67        }
68
69        Ok(build)
70    }
71}
72
73impl Deref for Rustc {
74    type Target = cargo_options::Rustc;
75
76    fn deref(&self) -> &Self::Target {
77        &self.cargo
78    }
79}
80
81impl DerefMut for Rustc {
82    fn deref_mut(&mut self) -> &mut Self::Target {
83        &mut self.cargo
84    }
85}
86
87impl From<cargo_options::Rustc> for Rustc {
88    fn from(cargo: cargo_options::Rustc) -> Self {
89        Self {
90            cargo,
91            ..Default::default()
92        }
93    }
94}