spirv_builder/
cargo_cmd.rs1use std::collections::HashSet;
2use std::env;
3use std::ffi::{OsStr, OsString};
4use std::fmt::{Display, Formatter};
5use std::ops::{Deref, DerefMut};
6use std::process::Command;
7
8pub struct CargoCmd {
12 cargo: Command,
13 vars_os: Vec<(OsString, OsString)>,
14 removed: HashSet<OsString>,
15}
16
17impl CargoCmd {
18 pub fn new() -> Self {
19 let mut cargo = CargoCmd::new_no_filtering();
20
21 cargo.retain_vars_os(|(key, _)| {
25 !key.to_str()
26 .is_some_and(|s| s.starts_with("CARGO_FEATURES_") || s.starts_with("CARGO_CFG_"))
27 });
28
29 cargo.env("CARGO_CACHE_RUSTC_INFO", "0");
34
35 cargo.env_remove("RUSTC");
40
41 cargo.env_remove("RUSTC_WRAPPER");
45
46 cargo
49 .env_remove("RUSTC_WORKSPACE_WRAPPER")
50 .env_remove("RUSTFLAGS")
51 .env_remove("CARGO")
52 .env_remove("RUSTUP_TOOLCHAIN");
53
54 cargo.env_remove("CARGO_ENCODED_RUSTFLAGS");
56
57 cargo.env_remove("CARGO_TARGET_DIR");
61
62 cargo
63 }
64
65 pub fn new_no_filtering() -> Self {
66 Self {
67 cargo: Command::new("cargo"),
68 vars_os: env::vars_os().collect(),
69 removed: HashSet::default(),
70 }
71 }
72
73 pub fn retain_vars_os(&mut self, mut f: impl FnMut((&OsString, &OsString)) -> bool) {
74 for (key, value) in &self.vars_os {
75 if !f((key, value)) {
76 self.removed.insert(key.clone());
77 self.cargo.env_remove(key);
78 }
79 }
80 }
81
82 pub fn env_remove(&mut self, key: impl AsRef<OsStr>) -> &mut Self {
83 self.removed.insert(key.as_ref().to_os_string());
84 self.cargo.env_remove(key);
85 self
86 }
87
88 pub fn env(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<OsStr>) -> &mut Self {
89 self.removed.remove(key.as_ref());
90 self.cargo.env(key, val);
91 self
92 }
93
94 pub fn env_var_report(&self) -> EnvVarReport {
95 let mut inherited = self.vars_os.clone();
96 inherited.retain(|(key, _)| !self.removed.contains(key));
97 EnvVarReport {
98 inherited,
99 removed: self.removed.clone(),
100 }
101 }
102}
103
104impl Default for CargoCmd {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110impl Display for CargoCmd {
111 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
112 f.debug_struct("CargoCmd")
113 .field("cargo", &self.cargo)
114 .field("env_vars", &self.env_var_report())
115 .finish()
116 }
117}
118
119impl Deref for CargoCmd {
120 type Target = Command;
121
122 fn deref(&self) -> &Self::Target {
123 &self.cargo
124 }
125}
126
127impl DerefMut for CargoCmd {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 &mut self.cargo
130 }
131}
132
133#[derive(Clone, Debug, Default)]
134pub struct EnvVarReport {
135 pub inherited: Vec<(OsString, OsString)>,
136 pub removed: HashSet<OsString>,
137}
138
139impl Display for EnvVarReport {
140 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
141 let removed = self
142 .removed
143 .iter()
144 .map(|key| format!("{}", key.to_string_lossy()))
145 .collect::<Vec<_>>();
146 let inherited = self
147 .inherited
148 .iter()
149 .map(|(key, value)| format!("{}: {}", key.to_string_lossy(), value.to_string_lossy()))
150 .collect::<Vec<_>>();
151
152 f.debug_struct("EnvVarReport")
153 .field("removed", &removed)
154 .field("inherited", &inherited)
155 .finish()
156 }
157}