1//! This module serves two purposes:
2//! 1. It is part of the `utils` module and used in other parts of bootstrap.
3//! 2. It is embedded inside bootstrap shims to avoid a dependency on the bootstrap library.
4//! Therefore, this module should never use any other bootstrap module. This reduces binary
5//! size and improves compilation time by minimizing linking time.
67#![allow(dead_code)]
89use std::env;
10use std::ffi::OsString;
11use std::fs::OpenOptions;
12use std::io::Write;
13use std::process::Command;
14use std::str::FromStr;
1516// If we were to declare a tests submodule here, the shim binaries that include this
17// module via `#[path]` would fail to find it, which breaks `./x check bootstrap`.
18// So instead the unit tests for this module are in `super::tests::shared_helpers_tests`.
1920/// Returns the environment variable which the dynamic library lookup path
21/// resides in for this platform.
22pub fn dylib_path_var() -> &'static str {
23if cfg!(target_os = "windows") {
24"PATH"
25} else if cfg!(target_vendor = "apple") {
26"DYLD_LIBRARY_PATH"
27} else if cfg!(target_os = "haiku") {
28"LIBRARY_PATH"
29} else if cfg!(target_os = "aix") {
30"LIBPATH"
31} else {
32"LD_LIBRARY_PATH"
33}
34}
3536/// Parses the `dylib_path_var()` environment variable, returning a list of
37/// paths that are members of this lookup path.
38pub fn dylib_path() -> Vec<std::path::PathBuf> {
39let var = match std::env::var_os(dylib_path_var()) {
40Some(v) => v,
41None => return vec![],
42 };
43 std::env::split_paths(&var).collect()
44}
4546/// Given an executable called `name`, return the filename for the
47/// executable for a particular target.
48pub fn exe(name: &str, target: &str) -> String {
49if target.contains("windows") {
50format!("{name}.exe")
51 } else if target.contains("uefi") {
52format!("{name}.efi")
53 } else if target.contains("wasm") {
54format!("{name}.wasm")
55 } else {
56 name.to_string()
57 }
58}
5960/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`.
61/// If it was not defined, returns 0 by default.
62///
63/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer.
64pub fn parse_rustc_verbose() -> usize {
65match env::var("RUSTC_VERBOSE") {
66Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
67Err(_) => 0,
68 }
69}
7071/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`.
72///
73/// If "RUSTC_STAGE" was not set, the program will be terminated with 101.
74pub fn parse_rustc_stage() -> String {
75 env::var("RUSTC_STAGE").unwrap_or_else(|_| {
76// Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
77eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set");
78eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap");
79 std::process::exit(101);
80 })
81}
8283/// Writes the command invocation to a file if `DUMP_BOOTSTRAP_SHIMS` is set during bootstrap.
84///
85/// Before writing it, replaces user-specific values to create generic dumps for cross-environment
86/// comparisons.
87pub fn maybe_dump(dump_name: String, cmd: &Command) {
88if let Ok(dump_dir) = env::var("DUMP_BOOTSTRAP_SHIMS") {
89let dump_file = format!("{dump_dir}/{dump_name}");
9091let mut file = OpenOptions::new().create(true).append(true).open(dump_file).unwrap();
9293let cmd_dump = format!("{:?}\n", cmd);
94let cmd_dump = cmd_dump.replace(&env::var("BUILD_OUT").unwrap(), "${BUILD_OUT}");
95let cmd_dump = cmd_dump.replace(&env::var("CARGO_HOME").unwrap(), "${CARGO_HOME}");
9697 file.write_all(cmd_dump.as_bytes()).expect("Unable to write file");
98 }
99}
100101/// Finds `key` and returns its value from the given list of arguments `args`.
102pub fn parse_value_from_args<'a>(args: &'a [OsString], key: &str) -> Option<&'a str> {
103let mut args = args.iter();
104while let Some(arg) = args.next() {
105let arg = arg.to_str().unwrap();
106107if let Some(value) = arg.strip_prefix(&format!("{key}=")) {
108return Some(value);
109 } else if arg == key {
110return args.next().map(|v| v.to_str().unwrap());
111 }
112 }
113114None
115}