bootstrap/utils/
shared_helpers.rs1#![allow(dead_code)]
15
16use std::env;
17use std::ffi::OsString;
18use std::fs::OpenOptions;
19use std::io::{BufRead, Write};
20use std::path::Path;
21use std::process::Command;
22use std::str::FromStr;
23
24pub fn dylib_path_var() -> &'static str {
27 if cfg!(any(target_os = "windows", target_os = "cygwin")) {
28 "PATH"
29 } else if cfg!(target_vendor = "apple") {
30 "DYLD_LIBRARY_PATH"
31 } else if cfg!(target_os = "haiku") {
32 "LIBRARY_PATH"
33 } else if cfg!(target_os = "aix") {
34 "LIBPATH"
35 } else {
36 "LD_LIBRARY_PATH"
37 }
38}
39
40pub fn dylib_path() -> Vec<std::path::PathBuf> {
43 let var = match std::env::var_os(dylib_path_var()) {
44 Some(v) => v,
45 None => return vec![],
46 };
47 std::env::split_paths(&var).collect()
48}
49
50pub fn exe(name: &str, target: &str) -> String {
53 if target.contains("windows") || (cfg!(not(target_os = "cygwin")) && target.contains("cygwin"))
62 {
63 format!("{name}.exe")
64 } else if target.contains("uefi") {
65 format!("{name}.efi")
66 } else if target.contains("wasm") {
67 format!("{name}.wasm")
68 } else {
69 name.to_string()
70 }
71}
72
73pub fn parse_rustc_verbose() -> usize {
78 match env::var("RUSTC_VERBOSE") {
79 Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
80 Err(_) => 0,
81 }
82}
83
84pub fn parse_rustc_stage() -> u32 {
89 env::var("RUSTC_STAGE").ok().and_then(|v| v.parse().ok()).unwrap_or_else(|| {
90 eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set");
92 eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap");
93 std::process::exit(101);
94 })
95}
96
97pub fn maybe_dump(dump_name: String, cmd: &Command) {
102 if let Ok(dump_dir) = env::var("DUMP_BOOTSTRAP_SHIMS") {
103 let dump_file = format!("{dump_dir}/{dump_name}");
104
105 let mut file = OpenOptions::new().create(true).append(true).open(dump_file).unwrap();
106
107 let cmd_dump = format!("{cmd:?}\n");
108 let cmd_dump = cmd_dump.replace(&env::var("BUILD_OUT").unwrap(), "${BUILD_OUT}");
109 let cmd_dump = cmd_dump.replace(&env::var("CARGO_HOME").unwrap(), "${CARGO_HOME}");
110
111 file.write_all(cmd_dump.as_bytes()).expect("Unable to write file");
112 }
113}
114
115pub fn parse_value_from_args<'a>(args: &'a [OsString], key: &str) -> Option<&'a str> {
117 let mut args = args.iter();
118 while let Some(arg) = args.next() {
119 let arg = arg.to_str().unwrap();
120
121 if let Some(value) = arg.strip_prefix(&format!("{key}=")) {
122 return Some(value);
123 } else if arg == key {
124 return args.next().map(|v| v.to_str().unwrap());
125 }
126 }
127
128 None
129}
130
131pub fn collect_args() -> Vec<OsString> {
133 let mut args = Vec::with_capacity(env::args_os().len());
134 for arg in env::args_os().skip(1) {
135 if let Some(s) = arg.to_str()
136 && let Some(path) = s.strip_prefix('@')
137 {
138 args.extend(args_from_argfile(Path::new(path)));
139 } else {
140 args.push(arg)
141 }
142 }
143 args
144}
145
146fn args_from_argfile(path: &Path) -> Vec<OsString> {
149 fn collect_lines(path: &Path) -> Result<Vec<OsString>, std::io::Error> {
150 let file = std::fs::File::open(path)?;
151 let lines: Result<Vec<OsString>, std::io::Error> =
152 std::io::BufReader::new(file).lines().map(|r| r.map(OsString::from)).collect();
153 lines
154 }
155 collect_lines(path).expect("read args from argfile {path:?}")
156}