raz_core/
rustc_options.rs1pub fn translate_cargo_to_rustc(option: &str) -> Option<&'static str> {
5 match option {
6 "--release" => Some("-O"),
7 "--debug" => Some("-g"),
8 "--target" => Some("--target"), "--verbose" | "-v" => Some("-v"),
10 "--quiet" | "-q" => None, "--features" => None, "--all-features" => None, "--no-default-features" => None, "--bin" => None, "--lib" => Some("--crate-type=lib"),
16 "--example" => None, "--test" => Some("--test"),
18 "--bench" => None, _ => None,
20 }
21}
22
23pub fn is_valid_rustc_option(option: &str) -> bool {
25 if option.len() == 2 && option.starts_with('-') {
27 matches!(
28 option,
29 "-h" | "-g"
30 | "-O"
31 | "-o"
32 | "-A"
33 | "-W"
34 | "-D"
35 | "-F"
36 | "-C"
37 | "-V"
38 | "-v"
39 | "-L"
40 | "-l"
41 )
42 } else if option.starts_with("--") {
43 matches!(
45 option,
46 "--help"
47 | "--cfg"
48 | "--check-cfg"
49 | "--crate-type"
50 | "--crate-name"
51 | "--edition"
52 | "--emit"
53 | "--print"
54 | "--out-dir"
55 | "--explain"
56 | "--test"
57 | "--target"
58 | "--allow"
59 | "--warn"
60 | "--force-warn"
61 | "--deny"
62 | "--forbid"
63 | "--cap-lints"
64 | "--codegen"
65 | "--version"
66 | "--verbose"
67 | "--extern"
68 | "--sysroot"
69 | "--error-format"
70 | "--json"
71 | "--color"
72 | "--diagnostic-width"
73 | "--remap-path-prefix"
74 | "--env-set"
75 )
76 } else if option.starts_with("-C") || option.starts_with("--codegen") {
77 true
79 } else if option.starts_with("-L") || option.starts_with("-l") {
80 true
82 } else {
83 false
84 }
85}
86
87pub fn get_rustc_optimization_flags(profile: &str) -> Vec<&'static str> {
89 match profile {
90 "release" => vec!["-O", "-C", "lto=yes", "-C", "codegen-units=1"],
91 "debug" => vec!["-g", "-C", "opt-level=0"],
92 "test" => vec!["--test", "-g"],
93 _ => vec![],
94 }
95}
96
97pub fn get_rustc_translation_help() -> &'static str {
99 r#"Cargo to Rustc Option Translation:
100
101Common Cargo options and their Rustc equivalents:
102 --release → -O (optimize) + -C lto=yes + -C codegen-units=1
103 --debug → -g (debug info)
104 --test → --test (build test harness)
105 --lib → --crate-type=lib
106 --target <TARGET> → --target <TARGET>
107 --verbose/-v → -v
108
109Options with no Rustc equivalent (will be ignored):
110 --features, --all-features, --no-default-features
111 --bin, --example, --bench
112 --quiet/-q
113
114For rustc scripts, you can use native rustc options:
115 -O Optimize (equivalent to -C opt-level=3)
116 -g Include debug info
117 -C <OPT>=<VAL> Set codegen options (e.g., -C lto=yes)
118 --edition Set Rust edition (2015|2018|2021|2024)
119 --crate-type Set output type (bin|lib|rlib|dylib|cdylib|staticlib)
120
121Example overrides for rustc:
122 -O # Optimize for release
123 -g # Include debug symbols
124 --edition 2021 # Use Rust 2021 edition
125 -C target-cpu=native # Optimize for native CPU
126"#
127}
128
129pub fn validate_and_translate_options(options: &[String], is_rustc: bool) -> Vec<String> {
131 if !is_rustc {
132 return options.to_vec();
133 }
134
135 let mut translated = Vec::new();
136 let mut skip_next = false;
137
138 for (i, option) in options.iter().enumerate() {
139 if skip_next {
140 skip_next = false;
141 continue;
142 }
143
144 if let Some(rustc_opt) = translate_cargo_to_rustc(option) {
146 translated.push(rustc_opt.to_string());
147
148 if matches!(option.as_str(), "--target") && i + 1 < options.len() {
150 translated.push(options[i + 1].clone());
151 skip_next = true;
152 }
153 } else if is_valid_rustc_option(option) {
154 translated.push(option.clone());
156
157 if needs_value(option) && i + 1 < options.len() && !options[i + 1].starts_with('-') {
159 translated.push(options[i + 1].clone());
160 skip_next = true;
161 }
162 } else if option == "--profile" && i + 1 < options.len() {
163 let profile = &options[i + 1];
165 translated.extend(
166 get_rustc_optimization_flags(profile)
167 .iter()
168 .map(|s| s.to_string()),
169 );
170 skip_next = true;
171 }
172 }
174
175 translated
176}
177
178fn needs_value(option: &str) -> bool {
180 matches!(
181 option,
182 "--cfg"
183 | "--check-cfg"
184 | "--crate-type"
185 | "--crate-name"
186 | "--edition"
187 | "--emit"
188 | "--print"
189 | "--out-dir"
190 | "--explain"
191 | "--target"
192 | "--allow"
193 | "--warn"
194 | "--force-warn"
195 | "--deny"
196 | "--forbid"
197 | "--cap-lints"
198 | "--codegen"
199 | "-o"
200 | "-L"
201 | "-l"
202 | "--extern"
203 | "--sysroot"
204 | "--error-format"
205 | "--json"
206 | "--color"
207 | "--diagnostic-width"
208 | "--remap-path-prefix"
209 | "--env-set"
210 ) || option == "-C"
211 || option == "-A"
212 || option == "-W"
213 || option == "-D"
214 || option == "-F"
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[test]
222 fn test_translate_cargo_to_rustc() {
223 assert_eq!(translate_cargo_to_rustc("--release"), Some("-O"));
224 assert_eq!(translate_cargo_to_rustc("--debug"), Some("-g"));
225 assert_eq!(translate_cargo_to_rustc("--test"), Some("--test"));
226 assert_eq!(translate_cargo_to_rustc("--lib"), Some("--crate-type=lib"));
227 assert_eq!(translate_cargo_to_rustc("--features"), None);
228 }
229
230 #[test]
231 fn test_is_valid_rustc_option() {
232 assert!(is_valid_rustc_option("-O"));
233 assert!(is_valid_rustc_option("-g"));
234 assert!(is_valid_rustc_option("--test"));
235 assert!(is_valid_rustc_option("--target"));
236 assert!(is_valid_rustc_option("-C"));
237 assert!(!is_valid_rustc_option("--release"));
238 assert!(!is_valid_rustc_option("--features"));
239 }
240
241 #[test]
242 fn test_validate_and_translate_options() {
243 let options = vec![
244 "--release".to_string(),
245 "--target".to_string(),
246 "wasm32-unknown-unknown".to_string(),
247 "--features".to_string(),
248 "foo,bar".to_string(),
249 ];
250
251 let translated = validate_and_translate_options(&options, true);
252 assert_eq!(
253 translated,
254 vec![
255 "-O".to_string(),
256 "--target".to_string(),
257 "wasm32-unknown-unknown".to_string(),
258 ]
259 );
260 }
261}