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#[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 #[arg(skip)]
20 pub disable_zig_linker: bool,
21
22 #[arg(skip)]
24 pub enable_zig_ar: bool,
25
26 #[arg(skip)]
28 pub macosx_deployment_target: Option<String>,
29
30 #[command(flatten)]
31 pub cargo: cargo_options::Rustc,
32}
33
34impl Rustc {
35 #[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 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 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}