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    #[command(flatten)]
27    pub cargo: cargo_options::Rustc,
28}
29
30impl Rustc {
31    /// Create a new build from manifest path
32    #[allow(clippy::field_reassign_with_default)]
33    pub fn new(manifest_path: Option<PathBuf>) -> Self {
34        let mut build = Self::default();
35        build.manifest_path = manifest_path;
36        build
37    }
38
39    /// Execute `cargo rustc` command with zig as the linker
40    pub fn execute(&self) -> Result<()> {
41        let mut rustc = self.build_command()?;
42
43        let mut child = rustc.spawn().context("Failed to run cargo rustc")?;
44        let status = child.wait().expect("Failed to wait on cargo build process");
45        if !status.success() {
46            process::exit(status.code().unwrap_or(1));
47        }
48        Ok(())
49    }
50
51    /// Generate cargo subcommand
52    pub fn build_command(&self) -> Result<Command> {
53        let mut build = self.cargo.command();
54        if !self.disable_zig_linker {
55            Zig::apply_command_env(
56                self.manifest_path.as_deref(),
57                self.release,
58                &self.cargo.common,
59                &mut build,
60                self.enable_zig_ar,
61            )?;
62        }
63
64        Ok(build)
65    }
66}
67
68impl Deref for Rustc {
69    type Target = cargo_options::Rustc;
70
71    fn deref(&self) -> &Self::Target {
72        &self.cargo
73    }
74}
75
76impl DerefMut for Rustc {
77    fn deref_mut(&mut self) -> &mut Self::Target {
78        &mut self.cargo
79    }
80}
81
82impl From<cargo_options::Rustc> for Rustc {
83    fn from(cargo: cargo_options::Rustc) -> Self {
84        Self {
85            cargo,
86            ..Default::default()
87        }
88    }
89}