1use std::path::PathBuf;
2use std::sync::OnceLock;
3
4use rustc_data_structures::profiling::VerboseTimingGuard;
5use rustc_fs_util::try_canonicalize;
6use rustc_hir::attrs::NativeLibKind;
7use rustc_macros::{Decodable, Encodable, HashStable_Generic};
8
9use crate::session::Session;
10
11impl Session {
12 pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
13 self.prof.verbose_generic_activity(what)
14 }
15 pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
17 self.prof.verbose_generic_activity(what).run(f)
18 }
19}
20
21#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
22#[derive(HashStable_Generic)]
23pub struct NativeLib {
24 pub name: String,
25 pub new_name: Option<String>,
26 pub kind: NativeLibKind,
27 pub verbatim: Option<bool>,
28}
29
30impl NativeLib {
31 pub fn has_modifiers(&self) -> bool {
32 self.verbatim.is_some() || self.kind.has_modifiers()
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
38pub struct CanonicalizedPath {
39 canonicalized: Option<PathBuf>,
41 original: PathBuf,
42}
43
44impl CanonicalizedPath {
45 pub fn new(path: PathBuf) -> Self {
46 Self { canonicalized: try_canonicalize(&path).ok(), original: path }
47 }
48
49 pub fn canonicalized(&self) -> &PathBuf {
50 self.canonicalized.as_ref().unwrap_or(self.original())
51 }
52
53 pub fn original(&self) -> &PathBuf {
54 &self.original
55 }
56}
57
58pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
64 const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
65
66 const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
67
68 const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
69
70 let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string());
71
72 let mut result = Vec::new();
73 let mut excluded_cargo_defaults = false;
74 while let Some(arg) = args.next() {
75 if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
76 let content = if arg.len() == a.len() {
77 match args.next() {
79 Some(arg) => arg,
80 None => continue,
81 }
82 } else if arg.get(a.len()..a.len() + 1) == Some("=") {
83 arg[a.len() + 1..].to_string()
85 } else {
86 arg[a.len()..].to_string()
88 };
89 let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
90 if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&option) {
91 excluded_cargo_defaults = true;
92 } else {
93 result.push(a.to_string());
94 result.push(if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&option) {
95 format!("{option}=[REDACTED]")
96 } else {
97 content
98 });
99 }
100 }
101 }
102
103 if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
104}
105
106pub fn was_invoked_from_cargo() -> bool {
111 static FROM_CARGO: OnceLock<bool> = OnceLock::new();
112
113 *FROM_CARGO.get_or_init(|| std::env::var_os("CARGO_CRATE_NAME").is_some())
119}