diff options
Diffstat (limited to 'compiler/rustc_session/src/config.rs')
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 153 |
1 files changed, 77 insertions, 76 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 56b3fe2ab4c..ff7ea5bd718 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -14,6 +14,7 @@ use std::str::{self, FromStr}; use std::sync::LazyLock; use std::{cmp, fmt, fs, iter}; +use externs::{ExternOpt, split_extern_opt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_errors::emitter::HumanReadableErrorType; @@ -39,6 +40,7 @@ use crate::utils::CanonicalizedPath; use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; mod cfg; +mod externs; mod native_libs; pub mod sigpipe; @@ -1015,11 +1017,14 @@ impl OutFileName { &self, outputs: &OutputFilenames, flavor: OutputType, - codegen_unit_name: Option<&str>, + codegen_unit_name: &str, + invocation_temp: Option<&str>, ) -> PathBuf { match *self { OutFileName::Real(ref path) => path.clone(), - OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), + OutFileName::Stdout => { + outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp) + } } } @@ -1094,40 +1099,59 @@ impl OutputFilenames { /// Gets the path where a compilation artifact of the given type for the /// given codegen unit should be placed on disk. If codegen_unit_name is /// None, a path distinct from those of any codegen unit will be generated. - pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { + pub fn temp_path_for_cgu( + &self, + flavor: OutputType, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { let extension = flavor.extension(); - self.temp_path_ext(extension, codegen_unit_name) + self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but specifically for dwarf objects. - pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { - self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) + pub fn temp_path_dwo_for_cgu( + &self, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but also supports things where there is no corresponding /// OutputType, like noopt-bitcode or lto-bitcode. - pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { - let mut extension = String::new(); + pub fn temp_path_ext_for_cgu( + &self, + ext: &str, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + let mut extension = codegen_unit_name.to_string(); - if let Some(codegen_unit_name) = codegen_unit_name { - extension.push_str(codegen_unit_name); + // Append `.{invocation_temp}` to ensure temporary files are unique. + if let Some(rng) = invocation_temp { + extension.push('.'); + extension.push_str(rng); } + // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty. + // Append `.rcgu.{ext}`. if !ext.is_empty() { - if !extension.is_empty() { - extension.push('.'); - extension.push_str(RUST_CGU_EXT); - extension.push('.'); - } - + extension.push('.'); + extension.push_str(RUST_CGU_EXT); + extension.push('.'); extension.push_str(ext); } let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(temps_directory, &extension) } + pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf { + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + self.with_directory_and_extension(temps_directory, &ext) + } + pub fn with_extension(&self, extension: &str) -> PathBuf { self.with_directory_and_extension(&self.out_directory, extension) } @@ -1144,10 +1168,11 @@ impl OutputFilenames { &self, split_debuginfo_kind: SplitDebuginfo, split_dwarf_kind: SplitDwarfKind, - cgu_name: Option<&str>, + cgu_name: &str, + invocation_temp: Option<&str>, ) -> Option<PathBuf> { - let obj_out = self.temp_path(OutputType::Object, cgu_name); - let dwo_out = self.temp_path_dwo(cgu_name); + let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp); + let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp); match (split_debuginfo_kind, split_dwarf_kind) { (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes @@ -1537,9 +1562,10 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE ) }); -static PRINT_KINDS_STRING: LazyLock<String> = LazyLock::new(|| { +static PRINT_HELP: LazyLock<String> = LazyLock::new(|| { format!( - "[{}]", + "Compiler information to print on stdout (or to a file)\n\ + INFO may be one of ({}).", PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|") ) }); @@ -1598,14 +1624,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> { "Comma separated list of types of output for the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", ), - opt( - Stable, - Multi, - "", - "print", - "Compiler information to print on stdout", - &PRINT_KINDS_STRING, - ), + opt(Stable, Multi, "", "print", &PRINT_HELP, "INFO[=FILE]"), opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""), opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"), @@ -2046,7 +2065,8 @@ fn collect_print_requests( check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind)); *print_kind } else { - emit_unknown_print_request_help(early_dcx, req) + let is_nightly = nightly_options::match_is_nightly_build(matches); + emit_unknown_print_request_help(early_dcx, req, is_nightly) }; let out = out.unwrap_or(OutFileName::Stdout); @@ -2070,25 +2090,37 @@ fn check_print_request_stability( unstable_opts: &UnstableOptions, (print_name, print_kind): (&str, PrintKind), ) { + if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options { + early_dcx.early_fatal(format!( + "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ + print option" + )); + } +} + +fn is_print_request_stable(print_kind: PrintKind) -> bool { match print_kind { PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::CrateRootLintLevels | PrintKind::SupportedCrateTypes - | PrintKind::TargetSpecJson - if !unstable_opts.unstable_options => - { - early_dcx.early_fatal(format!( - "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ - print option" - )); - } - _ => {} + | PrintKind::TargetSpecJson => false, + _ => true, } } -fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! { - let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); +fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! { + let prints = PRINT_KINDS + .iter() + .filter_map(|(name, kind)| { + // If we're not on nightly, we don't want to print unstable options + if !is_nightly && !is_print_request_stable(*kind) { + None + } else { + Some(format!("`{name}`")) + } + }) + .collect::<Vec<_>>(); let prints = prints.join(", "); let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); @@ -2188,44 +2220,13 @@ pub fn parse_externs( matches: &getopts::Matches, unstable_opts: &UnstableOptions, ) -> Externs { - fn is_ascii_ident(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() - && (start.is_ascii_alphabetic() || start == '_') - { - chars.all(|char| char.is_ascii_alphanumeric() || char == '_') - } else { - false - } - } - let is_unstable_enabled = unstable_opts.unstable_options; let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new(); for arg in matches.opt_strs("extern") { - let (name, path) = match arg.split_once('=') { - None => (arg, None), - Some((name, path)) => (name.to_string(), Some(Path::new(path))), - }; - let (options, name) = match name.split_once(':') { - None => (None, name), - Some((opts, name)) => (Some(opts), name.to_string()), - }; - - if !is_ascii_ident(&name) { - let mut error = early_dcx.early_struct_fatal(format!( - "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" - )); - let adjusted_name = name.replace('-', "_"); - if is_ascii_ident(&adjusted_name) { - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME - error.help(format!( - "consider replacing the dashes with underscores: `{adjusted_name}`" - )); - } - error.emit(); - } + let ExternOpt { crate_name: name, path, options } = + split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit()); - let path = path.map(|p| CanonicalizedPath::new(p)); + let path = path.map(|p| CanonicalizedPath::new(p.as_path())); let entry = externs.entry(name.to_owned()); |
