diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-07-21 06:52:28 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-21 06:52:28 +0200 |
| commit | b1d1e99c227b34f2864a1942f0096922a554acd5 (patch) | |
| tree | 78a1ab520674c23d6928977feca1c6b24e085054 /compiler/rustc_session | |
| parent | 2734b5ada9a34f31472e0d0ea9f4be043acecd66 (diff) | |
| parent | 11ae0afc931b00f921818eb99dd894768558bdcf (diff) | |
| download | rust-b1d1e99c227b34f2864a1942f0096922a554acd5.tar.gz rust-b1d1e99c227b34f2864a1942f0096922a554acd5.zip | |
Rollup merge of #113780 - dtolnay:printkindpath, r=b-naber
Support `--print KIND=PATH` command line syntax As is already done for `--emit KIND=PATH` and `-L KIND=PATH`. In the discussion of #110785, it was pointed out that `--print KIND=PATH` is nicer than trying to apply the single global `-o` path to `--print`'s output, because in general there can be multiple print requests within a single rustc invocation, and anyway `-o` would already be used for a different meaning in the case of `link-args` and `native-static-libs`. I am interested in using `--print cfg=PATH` in Buck2. Currently Buck2 works around the lack of support for `--print KIND=PATH` by [indirecting through a Python wrapper script](https://github.com/facebook/buck2/blob/d43cf3a51a31f00be2c2248e78271b0fef0452b4/prelude/rust/tools/get_rustc_cfg.py) to redirect rustc's stdout into the location dictated by the build system. From skimming Cargo's usages of `--print`, it definitely seems like it would benefit from `--print KIND=PATH` too. Currently it is working around the lack of this by inserting `--crate-name=___ --print=crate-name` so that it can look for a line containing `___` as a delimiter between the 2 other `--print` informations it actually cares about. This is commented as a "HACK" and "abuse". https://github.com/rust-lang/cargo/blob/31eda6f7c360d9911f853b3014e057db61238f3e/src/cargo/core/compiler/build_context/target_info.rs#L242 (FYI `@weihanglo` as you dealt with this recently in https://github.com/rust-lang/cargo/pull/11633.) Mentioning reviewers active in #110785: `@fee1-dead` `@jyn514` `@bjorn3`
Diffstat (limited to 'compiler/rustc_session')
| -rw-r--r-- | compiler/rustc_session/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 115 | ||||
| -rw-r--r-- | compiler/rustc_session/src/errors.rs | 7 |
3 files changed, 87 insertions, 37 deletions
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 4897bd8d5da..ee24c6d902f 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -26,6 +26,8 @@ session_feature_gate_error = {$explain} session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions +session_file_write_fail = failed to write `{$path}` due to error `{$err}` + session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 593983f117d..a8147ede970 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3,6 +3,7 @@ pub use crate::options::*; +use crate::errors::FileWriteFail; use crate::search_paths::SearchPath; use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; use crate::{lint, HashStableContext}; @@ -31,6 +32,7 @@ use std::collections::btree_map::{ use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsStr; use std::fmt; +use std::fs; use std::hash::Hash; use std::iter; use std::path::{Path, PathBuf}; @@ -710,8 +712,14 @@ impl ExternEntry { } } +#[derive(Clone, PartialEq, Debug)] +pub struct PrintRequest { + pub kind: PrintKind, + pub out: OutFileName, +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum PrintRequest { +pub enum PrintKind { FileNames, Sysroot, TargetLibdir, @@ -855,6 +863,17 @@ impl OutFileName { OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), } } + + pub fn overwrite(&self, content: &str, sess: &Session) { + match self { + OutFileName::Stdout => print!("{content}"), + OutFileName::Real(path) => { + if let Err(e) = fs::write(path, content) { + sess.emit_fatal(FileWriteFail { path, err: e.to_string() }); + } + } + } + } } #[derive(Clone, Hash, Debug, HashStable_Generic)] @@ -2005,13 +2024,7 @@ fn parse_output_types( if !unstable_opts.parse_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { - let (shorthand, path) = match output_type.split_once('=') { - None => (output_type, None), - Some((shorthand, "-")) => (shorthand, Some(OutFileName::Stdout)), - Some((shorthand, path)) => { - (shorthand, Some(OutFileName::Real(PathBuf::from(path)))) - } - }; + let (shorthand, path) = split_out_file_name(output_type); let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { handler.early_error(format!( "unknown emission type: `{shorthand}` - expected one of: {display}", @@ -2028,6 +2041,14 @@ fn parse_output_types( OutputTypes(output_types) } +fn split_out_file_name(arg: &str) -> (&str, Option<OutFileName>) { + match arg.split_once('=') { + None => (arg, None), + Some((kind, "-")) => (kind, Some(OutFileName::Stdout)), + Some((kind, path)) => (kind, Some(OutFileName::Real(PathBuf::from(path)))), + } +} + fn should_override_cgus_and_disable_thinlto( handler: &EarlyErrorHandler, output_types: &OutputTypes, @@ -2091,41 +2112,49 @@ fn collect_print_requests( ) -> Vec<PrintRequest> { let mut prints = Vec::<PrintRequest>::new(); if cg.target_cpu.as_ref().is_some_and(|s| s == "help") { - prints.push(PrintRequest::TargetCPUs); + prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); cg.target_cpu = None; }; if cg.target_feature == "help" { - prints.push(PrintRequest::TargetFeatures); + prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout }); cg.target_feature = String::new(); } - const PRINT_REQUESTS: &[(&str, PrintRequest)] = &[ - ("crate-name", PrintRequest::CrateName), - ("file-names", PrintRequest::FileNames), - ("sysroot", PrintRequest::Sysroot), - ("target-libdir", PrintRequest::TargetLibdir), - ("cfg", PrintRequest::Cfg), - ("calling-conventions", PrintRequest::CallingConventions), - ("target-list", PrintRequest::TargetList), - ("target-cpus", PrintRequest::TargetCPUs), - ("target-features", PrintRequest::TargetFeatures), - ("relocation-models", PrintRequest::RelocationModels), - ("code-models", PrintRequest::CodeModels), - ("tls-models", PrintRequest::TlsModels), - ("native-static-libs", PrintRequest::NativeStaticLibs), - ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), - ("target-spec-json", PrintRequest::TargetSpec), - ("all-target-specs-json", PrintRequest::AllTargetSpecs), - ("link-args", PrintRequest::LinkArgs), - ("split-debuginfo", PrintRequest::SplitDebuginfo), - ("deployment-target", PrintRequest::DeploymentTarget), + const PRINT_KINDS: &[(&str, PrintKind)] = &[ + ("crate-name", PrintKind::CrateName), + ("file-names", PrintKind::FileNames), + ("sysroot", PrintKind::Sysroot), + ("target-libdir", PrintKind::TargetLibdir), + ("cfg", PrintKind::Cfg), + ("calling-conventions", PrintKind::CallingConventions), + ("target-list", PrintKind::TargetList), + ("target-cpus", PrintKind::TargetCPUs), + ("target-features", PrintKind::TargetFeatures), + ("relocation-models", PrintKind::RelocationModels), + ("code-models", PrintKind::CodeModels), + ("tls-models", PrintKind::TlsModels), + ("native-static-libs", PrintKind::NativeStaticLibs), + ("stack-protector-strategies", PrintKind::StackProtectorStrategies), + ("target-spec-json", PrintKind::TargetSpec), + ("all-target-specs-json", PrintKind::AllTargetSpecs), + ("link-args", PrintKind::LinkArgs), + ("split-debuginfo", PrintKind::SplitDebuginfo), + ("deployment-target", PrintKind::DeploymentTarget), ]; + // We disallow reusing the same path in multiple prints, such as `--print + // cfg=output.txt --print link-args=output.txt`, because outputs are printed + // by disparate pieces of the compiler, and keeping track of which files + // need to be overwritten vs appended to is annoying. + let mut printed_paths = FxHashSet::default(); + prints.extend(matches.opt_strs("print").into_iter().map(|req| { - match PRINT_REQUESTS.iter().find(|&&(name, _)| name == req) { - Some((_, PrintRequest::TargetSpec)) => { + let (req, out) = split_out_file_name(&req); + + let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) { + Some((_, PrintKind::TargetSpec)) => { if unstable_opts.unstable_options { - PrintRequest::TargetSpec + PrintKind::TargetSpec } else { handler.early_error( "the `-Z unstable-options` flag must also be passed to \ @@ -2133,9 +2162,9 @@ fn collect_print_requests( ); } } - Some((_, PrintRequest::AllTargetSpecs)) => { + Some((_, PrintKind::AllTargetSpecs)) => { if unstable_opts.unstable_options { - PrintRequest::AllTargetSpecs + PrintKind::AllTargetSpecs } else { handler.early_error( "the `-Z unstable-options` flag must also be passed to \ @@ -2143,16 +2172,28 @@ fn collect_print_requests( ); } } - Some(&(_, print_request)) => print_request, + Some(&(_, print_kind)) => print_kind, None => { let prints = - PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); + PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); let prints = prints.join(", "); handler.early_error(format!( "unknown print request `{req}`. Valid print requests are: {prints}" )); } + }; + + let out = out.unwrap_or(OutFileName::Stdout); + if let OutFileName::Real(path) = &out { + if !printed_paths.insert(path.clone()) { + handler.early_error(format!( + "cannot print multiple outputs to the same path: {}", + path.display(), + )); + } } + + PrintRequest { kind, out } })); prints diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 4a3e668da11..dd15ad45145 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -164,6 +164,13 @@ pub struct FileIsNotWriteable<'a> { } #[derive(Diagnostic)] +#[diag(session_file_write_fail)] +pub(crate) struct FileWriteFail<'a> { + pub path: &'a std::path::Path, + pub err: String, +} + +#[derive(Diagnostic)] #[diag(session_crate_name_does_not_match)] pub struct CrateNameDoesNotMatch { #[primary_span] |
