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](d43cf3a51a/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".31eda6f7c3/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`
This commit is contained in:
commit
b1d1e99c22
21 changed files with 299 additions and 141 deletions
|
@ -40,7 +40,7 @@ use rustc_metadata::EncodedMetadata;
|
||||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
|
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
|
||||||
|
@ -284,10 +284,10 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(&self, req: PrintRequest, sess: &Session) {
|
fn print(&self, req: &PrintRequest, out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||||
match req {
|
match req.kind {
|
||||||
PrintRequest::RelocationModels => {
|
PrintKind::RelocationModels => {
|
||||||
println!("Available relocation models:");
|
writeln!(out, "Available relocation models:");
|
||||||
for name in &[
|
for name in &[
|
||||||
"static",
|
"static",
|
||||||
"pic",
|
"pic",
|
||||||
|
@ -298,26 +298,27 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
"ropi-rwpi",
|
"ropi-rwpi",
|
||||||
"default",
|
"default",
|
||||||
] {
|
] {
|
||||||
println!(" {}", name);
|
writeln!(out, " {}", name);
|
||||||
}
|
}
|
||||||
println!();
|
writeln!(out);
|
||||||
}
|
}
|
||||||
PrintRequest::CodeModels => {
|
PrintKind::CodeModels => {
|
||||||
println!("Available code models:");
|
writeln!(out, "Available code models:");
|
||||||
for name in &["tiny", "small", "kernel", "medium", "large"] {
|
for name in &["tiny", "small", "kernel", "medium", "large"] {
|
||||||
println!(" {}", name);
|
writeln!(out, " {}", name);
|
||||||
}
|
}
|
||||||
println!();
|
writeln!(out);
|
||||||
}
|
}
|
||||||
PrintRequest::TlsModels => {
|
PrintKind::TlsModels => {
|
||||||
println!("Available TLS models:");
|
writeln!(out, "Available TLS models:");
|
||||||
for name in &["global-dynamic", "local-dynamic", "initial-exec", "local-exec"] {
|
for name in &["global-dynamic", "local-dynamic", "initial-exec", "local-exec"] {
|
||||||
println!(" {}", name);
|
writeln!(out, " {}", name);
|
||||||
}
|
}
|
||||||
println!();
|
writeln!(out);
|
||||||
}
|
}
|
||||||
PrintRequest::StackProtectorStrategies => {
|
PrintKind::StackProtectorStrategies => {
|
||||||
println!(
|
writeln!(
|
||||||
|
out,
|
||||||
r#"Available stack protector strategies:
|
r#"Available stack protector strategies:
|
||||||
all
|
all
|
||||||
Generate stack canaries in all functions.
|
Generate stack canaries in all functions.
|
||||||
|
@ -341,7 +342,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
req => llvm_util::print(req, sess),
|
_other => llvm_util::print(req, out, sess),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2283,7 +2283,12 @@ extern "C" {
|
||||||
|
|
||||||
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
|
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
|
||||||
|
|
||||||
pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine, cpu: *const c_char);
|
pub fn LLVMRustPrintTargetCPUs(
|
||||||
|
T: &TargetMachine,
|
||||||
|
cpu: *const c_char,
|
||||||
|
print: unsafe extern "C" fn(out: *mut c_void, string: *const c_char, len: usize),
|
||||||
|
out: *mut c_void,
|
||||||
|
);
|
||||||
pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
|
pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
|
||||||
pub fn LLVMRustGetTargetFeature(
|
pub fn LLVMRustGetTargetFeature(
|
||||||
T: &TargetMachine,
|
T: &TargetMachine,
|
||||||
|
|
|
@ -8,16 +8,17 @@ use libc::c_int;
|
||||||
use rustc_codegen_ssa::target_features::{
|
use rustc_codegen_ssa::target_features::{
|
||||||
supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES,
|
supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES,
|
||||||
};
|
};
|
||||||
|
use rustc_codegen_ssa::traits::PrintBackendInfo;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_fs_util::path_to_c_string;
|
use rustc_fs_util::path_to_c_string;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_session::config::PrintRequest;
|
use rustc_session::config::{PrintKind, PrintRequest};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
|
|
||||||
|
use std::ffi::{c_char, c_void, CStr, CString};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -354,7 +355,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
|
fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &llvm::TargetMachine) {
|
||||||
let mut llvm_target_features = llvm_target_features(tm);
|
let mut llvm_target_features = llvm_target_features(tm);
|
||||||
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
|
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
|
||||||
let mut rustc_target_features = supported_target_features(sess)
|
let mut rustc_target_features = supported_target_features(sess)
|
||||||
|
@ -387,36 +388,48 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
println!("Features supported by rustc for this target:");
|
writeln!(out, "Features supported by rustc for this target:");
|
||||||
for (feature, desc) in &rustc_target_features {
|
for (feature, desc) in &rustc_target_features {
|
||||||
println!(" {1:0$} - {2}.", max_feature_len, feature, desc);
|
writeln!(out, " {1:0$} - {2}.", max_feature_len, feature, desc);
|
||||||
}
|
}
|
||||||
println!("\nCode-generation features supported by LLVM for this target:");
|
writeln!(out, "\nCode-generation features supported by LLVM for this target:");
|
||||||
for (feature, desc) in &llvm_target_features {
|
for (feature, desc) in &llvm_target_features {
|
||||||
println!(" {1:0$} - {2}.", max_feature_len, feature, desc);
|
writeln!(out, " {1:0$} - {2}.", max_feature_len, feature, desc);
|
||||||
}
|
}
|
||||||
if llvm_target_features.is_empty() {
|
if llvm_target_features.is_empty() {
|
||||||
println!(" Target features listing is not supported by this LLVM version.");
|
writeln!(out, " Target features listing is not supported by this LLVM version.");
|
||||||
}
|
}
|
||||||
println!("\nUse +feature to enable a feature, or -feature to disable it.");
|
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.");
|
||||||
println!("For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n");
|
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n");
|
||||||
println!("Code-generation features cannot be used in cfg or #[target_feature],");
|
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],");
|
||||||
println!("and may be renamed or removed in a future version of LLVM or rustc.\n");
|
writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn print(req: PrintRequest, sess: &Session) {
|
pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess: &Session) {
|
||||||
require_inited();
|
require_inited();
|
||||||
let tm = create_informational_target_machine(sess);
|
let tm = create_informational_target_machine(sess);
|
||||||
match req {
|
match req.kind {
|
||||||
PrintRequest::TargetCPUs => {
|
PrintKind::TargetCPUs => {
|
||||||
// SAFETY generate a C compatible string from a byte slice to pass
|
// SAFETY generate a C compatible string from a byte slice to pass
|
||||||
// the target CPU name into LLVM, the lifetime of the reference is
|
// the target CPU name into LLVM, the lifetime of the reference is
|
||||||
// at least as long as the C function
|
// at least as long as the C function
|
||||||
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
||||||
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
||||||
unsafe { llvm::LLVMRustPrintTargetCPUs(tm, cpu_cstring.as_ptr()) };
|
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
|
||||||
|
let out = &mut *(out as *mut &mut dyn PrintBackendInfo);
|
||||||
|
let bytes = slice::from_raw_parts(string as *const u8, len);
|
||||||
|
write!(out, "{}", String::from_utf8_lossy(bytes));
|
||||||
}
|
}
|
||||||
PrintRequest::TargetFeatures => print_target_features(sess, tm),
|
unsafe {
|
||||||
|
llvm::LLVMRustPrintTargetCPUs(
|
||||||
|
tm,
|
||||||
|
cpu_cstring.as_ptr(),
|
||||||
|
callback,
|
||||||
|
&mut out as *mut &mut dyn PrintBackendInfo as *mut c_void,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintKind::TargetFeatures => print_target_features(out, sess, tm),
|
||||||
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
|
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,8 @@ codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libr
|
||||||
|
|
||||||
codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
|
codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
|
||||||
|
|
||||||
|
codegen_ssa_static_library_native_artifacts_to_file = Native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms.
|
||||||
|
|
||||||
codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
|
codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
|
||||||
.note = {$output}
|
.note = {$output}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
|
||||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, Strip};
|
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, OutFileName, Strip};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
use rustc_session::config::{OutputFilenames, OutputType, PrintKind, SplitDwarfKind};
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_session::cstore::DllImport;
|
||||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||||
use rustc_session::search_paths::PathKind;
|
use rustc_session::search_paths::PathKind;
|
||||||
|
@ -596,8 +596,10 @@ fn link_staticlib<'a>(
|
||||||
|
|
||||||
all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);
|
all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);
|
||||||
|
|
||||||
if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
|
for print in &sess.opts.prints {
|
||||||
print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs);
|
if print.kind == PrintKind::NativeStaticLibs {
|
||||||
|
print_native_static_libs(sess, &print.out, &all_native_libs, &all_rust_dylibs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -744,8 +746,11 @@ fn link_natively<'a>(
|
||||||
cmd.env_remove(k.as_ref());
|
cmd.env_remove(k.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.opts.prints.contains(&PrintRequest::LinkArgs) {
|
for print in &sess.opts.prints {
|
||||||
println!("{:?}", &cmd);
|
if print.kind == PrintKind::LinkArgs {
|
||||||
|
let content = format!("{:?}", cmd);
|
||||||
|
print.out.overwrite(&content, sess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// May have not found libraries in the right formats.
|
// May have not found libraries in the right formats.
|
||||||
|
@ -1386,6 +1391,7 @@ enum RlibFlavor {
|
||||||
|
|
||||||
fn print_native_static_libs(
|
fn print_native_static_libs(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
|
out: &OutFileName,
|
||||||
all_native_libs: &[NativeLib],
|
all_native_libs: &[NativeLib],
|
||||||
all_rust_dylibs: &[&Path],
|
all_rust_dylibs: &[&Path],
|
||||||
) {
|
) {
|
||||||
|
@ -1459,6 +1465,15 @@ fn print_native_static_libs(
|
||||||
lib_args.push(format!("-l{}", lib));
|
lib_args.push(format!("-l{}", lib));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match out {
|
||||||
|
OutFileName::Real(path) => {
|
||||||
|
out.overwrite(&lib_args.join(" "), sess);
|
||||||
|
if !lib_args.is_empty() {
|
||||||
|
sess.emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OutFileName::Stdout => {
|
||||||
if !lib_args.is_empty() {
|
if !lib_args.is_empty() {
|
||||||
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
||||||
// Prefix for greppability
|
// Prefix for greppability
|
||||||
|
@ -1466,6 +1481,8 @@ fn print_native_static_libs(
|
||||||
sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" ")));
|
sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
|
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
|
||||||
let fs = sess.target_filesearch(PathKind::Native);
|
let fs = sess.target_filesearch(PathKind::Native);
|
||||||
|
|
|
@ -455,6 +455,12 @@ pub struct LinkerFileStem;
|
||||||
#[diag(codegen_ssa_static_library_native_artifacts)]
|
#[diag(codegen_ssa_static_library_native_artifacts)]
|
||||||
pub struct StaticLibraryNativeArtifacts;
|
pub struct StaticLibraryNativeArtifacts;
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(codegen_ssa_static_library_native_artifacts_to_file)]
|
||||||
|
pub struct StaticLibraryNativeArtifactsToFile<'a> {
|
||||||
|
pub path: &'a Path,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(codegen_ssa_link_script_unavailable)]
|
#[diag(codegen_ssa_link_script_unavailable)]
|
||||||
pub struct LinkScriptUnavailable;
|
pub struct LinkScriptUnavailable;
|
||||||
|
|
|
@ -23,6 +23,8 @@ use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
pub trait BackendTypes {
|
pub trait BackendTypes {
|
||||||
type Value: CodegenObject;
|
type Value: CodegenObject;
|
||||||
type Function: CodegenObject;
|
type Function: CodegenObject;
|
||||||
|
@ -61,7 +63,7 @@ pub trait CodegenBackend {
|
||||||
fn locale_resource(&self) -> &'static str;
|
fn locale_resource(&self) -> &'static str;
|
||||||
|
|
||||||
fn init(&self, _sess: &Session) {}
|
fn init(&self, _sess: &Session) {}
|
||||||
fn print(&self, _req: PrintRequest, _sess: &Session) {}
|
fn print(&self, _req: &PrintRequest, _out: &mut dyn PrintBackendInfo, _sess: &Session) {}
|
||||||
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
|
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
@ -162,3 +164,19 @@ pub trait ExtraBackendMethods:
|
||||||
std::thread::Builder::new().name(name).spawn(f)
|
std::thread::Builder::new().name(name).spawn(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PrintBackendInfo {
|
||||||
|
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintBackendInfo for String {
|
||||||
|
fn infallible_write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||||
|
fmt::Write::write_fmt(self, args).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dyn PrintBackendInfo + '_ {
|
||||||
|
pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||||
|
self.infallible_write_fmt(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,9 @@ mod write;
|
||||||
|
|
||||||
pub use self::abi::AbiBuilderMethods;
|
pub use self::abi::AbiBuilderMethods;
|
||||||
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
|
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
|
||||||
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
pub use self::backend::{
|
||||||
|
Backend, BackendTypes, CodegenBackend, ExtraBackendMethods, PrintBackendInfo,
|
||||||
|
};
|
||||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||||
pub use self::consts::ConstMethods;
|
pub use self::consts::ConstMethods;
|
||||||
pub use self::coverageinfo::CoverageInfoBuilderMethods;
|
pub use self::coverageinfo::CoverageInfoBuilderMethods;
|
||||||
|
|
|
@ -19,5 +19,3 @@ driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc ver
|
||||||
driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
|
driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
|
||||||
|
|
||||||
driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
|
driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
|
||||||
|
|
||||||
driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
|
|
||||||
|
|
|
@ -37,9 +37,7 @@ use rustc_interface::{interface, Queries};
|
||||||
use rustc_lint::LintStore;
|
use rustc_lint::LintStore;
|
||||||
use rustc_metadata::locator;
|
use rustc_metadata::locator;
|
||||||
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
|
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
|
||||||
use rustc_session::config::{
|
use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
|
||||||
ErrorOutputType, Input, OutFileName, OutputType, PrintRequest, TrimmedDefPaths,
|
|
||||||
};
|
|
||||||
use rustc_session::cstore::MetadataLoader;
|
use rustc_session::cstore::MetadataLoader;
|
||||||
use rustc_session::getopts::{self, Matches};
|
use rustc_session::getopts::{self, Matches};
|
||||||
use rustc_session::lint::{Lint, LintId};
|
use rustc_session::lint::{Lint, LintId};
|
||||||
|
@ -53,6 +51,7 @@ use std::cmp::max;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
use std::fmt::Write as _;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, IsTerminal, Read, Write};
|
use std::io::{self, IsTerminal, Read, Write};
|
||||||
use std::panic::{self, catch_unwind};
|
use std::panic::{self, catch_unwind};
|
||||||
|
@ -72,6 +71,11 @@ macro do_not_use_print($($t:tt)*) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro do_not_use_safe_print($($t:tt)*) {
|
||||||
|
std::compile_error!("Don't use `safe_print` or `safe_println` here, use `println_info` instead")
|
||||||
|
}
|
||||||
|
|
||||||
// This import blocks the use of panicking `print` and `println` in all the code
|
// This import blocks the use of panicking `print` and `println` in all the code
|
||||||
// below. Please use `safe_print` and `safe_println` to avoid ICE when
|
// below. Please use `safe_print` and `safe_println` to avoid ICE when
|
||||||
// encountering an I/O error during print.
|
// encountering an I/O error during print.
|
||||||
|
@ -720,10 +724,17 @@ fn print_crate_info(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
parse_attrs: bool,
|
parse_attrs: bool,
|
||||||
) -> Compilation {
|
) -> Compilation {
|
||||||
use rustc_session::config::PrintRequest::*;
|
use rustc_session::config::PrintKind::*;
|
||||||
|
|
||||||
|
// This import prevents the following code from using the printing macros
|
||||||
|
// used by the rest of the module. Within this function, we only write to
|
||||||
|
// the output specified by `sess.io.output_file`.
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use {do_not_use_safe_print as safe_print, do_not_use_safe_print as safe_println};
|
||||||
|
|
||||||
// NativeStaticLibs and LinkArgs are special - printed during linking
|
// NativeStaticLibs and LinkArgs are special - printed during linking
|
||||||
// (empty iterator returns true)
|
// (empty iterator returns true)
|
||||||
if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
|
if sess.opts.prints.iter().all(|p| p.kind == NativeStaticLibs || p.kind == LinkArgs) {
|
||||||
return Compilation::Continue;
|
return Compilation::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,17 +750,23 @@ fn print_crate_info(
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
for req in &sess.opts.prints {
|
for req in &sess.opts.prints {
|
||||||
match *req {
|
let mut crate_info = String::new();
|
||||||
|
macro println_info($($arg:tt)*) {
|
||||||
|
crate_info.write_fmt(format_args!("{}\n", format_args!($($arg)*))).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
match req.kind {
|
||||||
TargetList => {
|
TargetList => {
|
||||||
let mut targets = rustc_target::spec::TARGETS.to_vec();
|
let mut targets = rustc_target::spec::TARGETS.to_vec();
|
||||||
targets.sort_unstable();
|
targets.sort_unstable();
|
||||||
safe_println!("{}", targets.join("\n"));
|
println_info!("{}", targets.join("\n"));
|
||||||
}
|
}
|
||||||
Sysroot => safe_println!("{}", sess.sysroot.display()),
|
Sysroot => println_info!("{}", sess.sysroot.display()),
|
||||||
TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()),
|
TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()),
|
||||||
TargetSpec => {
|
TargetSpec => {
|
||||||
safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
|
println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
|
||||||
}
|
}
|
||||||
AllTargetSpecs => {
|
AllTargetSpecs => {
|
||||||
let mut targets = BTreeMap::new();
|
let mut targets = BTreeMap::new();
|
||||||
|
@ -758,26 +775,30 @@ fn print_crate_info(
|
||||||
let target = Target::expect_builtin(&triple);
|
let target = Target::expect_builtin(&triple);
|
||||||
targets.insert(name, target.to_json());
|
targets.insert(name, target.to_json());
|
||||||
}
|
}
|
||||||
safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap());
|
println_info!("{}", serde_json::to_string_pretty(&targets).unwrap());
|
||||||
}
|
}
|
||||||
FileNames | CrateName => {
|
FileNames => {
|
||||||
let Some(attrs) = attrs.as_ref() else {
|
let Some(attrs) = attrs.as_ref() else {
|
||||||
// no crate attributes, print out an error and exit
|
// no crate attributes, print out an error and exit
|
||||||
return Compilation::Continue;
|
return Compilation::Continue;
|
||||||
};
|
};
|
||||||
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
|
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
|
||||||
let id = rustc_session::output::find_crate_name(sess, attrs);
|
let id = rustc_session::output::find_crate_name(sess, attrs);
|
||||||
if *req == PrintRequest::CrateName {
|
|
||||||
safe_println!("{id}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let crate_types = collect_crate_types(sess, attrs);
|
let crate_types = collect_crate_types(sess, attrs);
|
||||||
for &style in &crate_types {
|
for &style in &crate_types {
|
||||||
let fname =
|
let fname =
|
||||||
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
||||||
safe_println!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
|
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CrateName => {
|
||||||
|
let Some(attrs) = attrs.as_ref() else {
|
||||||
|
// no crate attributes, print out an error and exit
|
||||||
|
return Compilation::Continue;
|
||||||
|
};
|
||||||
|
let id = rustc_session::output::find_crate_name(sess, attrs);
|
||||||
|
println_info!("{id}");
|
||||||
|
}
|
||||||
Cfg => {
|
Cfg => {
|
||||||
let mut cfgs = sess
|
let mut cfgs = sess
|
||||||
.parse_sess
|
.parse_sess
|
||||||
|
@ -809,13 +830,13 @@ fn print_crate_info(
|
||||||
|
|
||||||
cfgs.sort();
|
cfgs.sort();
|
||||||
for cfg in cfgs {
|
for cfg in cfgs {
|
||||||
safe_println!("{cfg}");
|
println_info!("{cfg}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallingConventions => {
|
CallingConventions => {
|
||||||
let mut calling_conventions = rustc_target::spec::abi::all_names();
|
let mut calling_conventions = rustc_target::spec::abi::all_names();
|
||||||
calling_conventions.sort_unstable();
|
calling_conventions.sort_unstable();
|
||||||
safe_println!("{}", calling_conventions.join("\n"));
|
println_info!("{}", calling_conventions.join("\n"));
|
||||||
}
|
}
|
||||||
RelocationModels
|
RelocationModels
|
||||||
| CodeModels
|
| CodeModels
|
||||||
|
@ -823,7 +844,7 @@ fn print_crate_info(
|
||||||
| TargetCPUs
|
| TargetCPUs
|
||||||
| StackProtectorStrategies
|
| StackProtectorStrategies
|
||||||
| TargetFeatures => {
|
| TargetFeatures => {
|
||||||
codegen_backend.print(*req, sess);
|
codegen_backend.print(req, &mut crate_info, sess);
|
||||||
}
|
}
|
||||||
// Any output here interferes with Cargo's parsing of other printed output
|
// Any output here interferes with Cargo's parsing of other printed output
|
||||||
NativeStaticLibs => {}
|
NativeStaticLibs => {}
|
||||||
|
@ -833,7 +854,7 @@ fn print_crate_info(
|
||||||
|
|
||||||
for split in &[Off, Packed, Unpacked] {
|
for split in &[Off, Packed, Unpacked] {
|
||||||
if sess.target.options.supported_split_debuginfo.contains(split) {
|
if sess.target.options.supported_split_debuginfo.contains(split) {
|
||||||
safe_println!("{split}");
|
println_info!("{split}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,7 +862,7 @@ fn print_crate_info(
|
||||||
use rustc_target::spec::current_apple_deployment_target;
|
use rustc_target::spec::current_apple_deployment_target;
|
||||||
|
|
||||||
if sess.target.is_like_osx {
|
if sess.target.is_like_osx {
|
||||||
safe_println!(
|
println_info!(
|
||||||
"deployment_target={}",
|
"deployment_target={}",
|
||||||
current_apple_deployment_target(&sess.target)
|
current_apple_deployment_target(&sess.target)
|
||||||
.expect("unknown Apple target OS")
|
.expect("unknown Apple target OS")
|
||||||
|
@ -852,6 +873,8 @@ fn print_crate_info(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.out.overwrite(&crate_info, sess);
|
||||||
}
|
}
|
||||||
Compilation::Stop
|
Compilation::Stop
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! The various pretty-printing routines.
|
//! The various pretty-printing routines.
|
||||||
|
|
||||||
use crate::session_diagnostics::UnprettyDumpFail;
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
|
@ -358,17 +357,7 @@ fn get_source(sess: &Session) -> (String, FileName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_or_print(out: &str, sess: &Session) {
|
fn write_or_print(out: &str, sess: &Session) {
|
||||||
match &sess.io.output_file {
|
sess.io.output_file.as_ref().unwrap_or(&OutFileName::Stdout).overwrite(out, sess);
|
||||||
None | Some(OutFileName::Stdout) => print!("{out}"),
|
|
||||||
Some(OutFileName::Real(p)) => {
|
|
||||||
if let Err(e) = std::fs::write(p, out) {
|
|
||||||
sess.emit_fatal(UnprettyDumpFail {
|
|
||||||
path: p.display().to_string(),
|
|
||||||
err: e.to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
|
pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
|
||||||
|
|
|
@ -32,13 +32,6 @@ pub(crate) struct RLinkRustcVersionMismatch<'a> {
|
||||||
#[diag(driver_impl_rlink_no_a_file)]
|
#[diag(driver_impl_rlink_no_a_file)]
|
||||||
pub(crate) struct RlinkNotAFile;
|
pub(crate) struct RlinkNotAFile;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(driver_impl_unpretty_dump_fail)]
|
|
||||||
pub(crate) struct UnprettyDumpFail {
|
|
||||||
pub path: String,
|
|
||||||
pub err: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(driver_impl_ice)]
|
#[diag(driver_impl_ice)]
|
||||||
pub(crate) struct Ice;
|
pub(crate) struct Ice;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
@ -306,44 +307,55 @@ static size_t getLongestEntryLength(ArrayRef<KV> Table) {
|
||||||
return MaxLen;
|
return MaxLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, const char* TargetCPU) {
|
using PrintBackendInfo = void(void*, const char* Data, size_t Len);
|
||||||
|
|
||||||
|
extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM,
|
||||||
|
const char* TargetCPU,
|
||||||
|
PrintBackendInfo Print,
|
||||||
|
void* Out) {
|
||||||
const TargetMachine *Target = unwrap(TM);
|
const TargetMachine *Target = unwrap(TM);
|
||||||
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
|
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
|
||||||
const Triple::ArchType HostArch = Triple(sys::getDefaultTargetTriple()).getArch();
|
const Triple::ArchType HostArch = Triple(sys::getDefaultTargetTriple()).getArch();
|
||||||
const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
|
const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
|
||||||
|
|
||||||
|
std::ostringstream Buf;
|
||||||
|
|
||||||
#if LLVM_VERSION_GE(17, 0)
|
#if LLVM_VERSION_GE(17, 0)
|
||||||
const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getAllProcessorDescriptions();
|
const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getAllProcessorDescriptions();
|
||||||
#elif defined(LLVM_RUSTLLVM)
|
#elif defined(LLVM_RUSTLLVM)
|
||||||
const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
|
const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
|
||||||
#else
|
#else
|
||||||
printf("Full target CPU help is not supported by this LLVM version.\n\n");
|
Buf << "Full target CPU help is not supported by this LLVM version.\n\n";
|
||||||
SubtargetSubTypeKV TargetCPUKV = { TargetCPU, {{}}, {{}} };
|
SubtargetSubTypeKV TargetCPUKV = { TargetCPU, {{}}, {{}} };
|
||||||
const ArrayRef<SubtargetSubTypeKV> CPUTable = TargetCPUKV;
|
const ArrayRef<SubtargetSubTypeKV> CPUTable = TargetCPUKV;
|
||||||
#endif
|
#endif
|
||||||
unsigned MaxCPULen = getLongestEntryLength(CPUTable);
|
unsigned MaxCPULen = getLongestEntryLength(CPUTable);
|
||||||
|
|
||||||
printf("Available CPUs for this target:\n");
|
Buf << "Available CPUs for this target:\n";
|
||||||
// Don't print the "native" entry when the user specifies --target with a
|
// Don't print the "native" entry when the user specifies --target with a
|
||||||
// different arch since that could be wrong or misleading.
|
// different arch since that could be wrong or misleading.
|
||||||
if (HostArch == TargetArch) {
|
if (HostArch == TargetArch) {
|
||||||
MaxCPULen = std::max(MaxCPULen, (unsigned) std::strlen("native"));
|
MaxCPULen = std::max(MaxCPULen, (unsigned) std::strlen("native"));
|
||||||
const StringRef HostCPU = sys::getHostCPUName();
|
const StringRef HostCPU = sys::getHostCPUName();
|
||||||
printf(" %-*s - Select the CPU of the current host (currently %.*s).\n",
|
Buf << " " << std::left << std::setw(MaxCPULen) << "native"
|
||||||
MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data());
|
<< " - Select the CPU of the current host "
|
||||||
|
"(currently " << HostCPU.str() << ").\n";
|
||||||
}
|
}
|
||||||
for (auto &CPU : CPUTable) {
|
for (auto &CPU : CPUTable) {
|
||||||
// Compare cpu against current target to label the default
|
// Compare cpu against current target to label the default
|
||||||
if (strcmp(CPU.Key, TargetCPU) == 0) {
|
if (strcmp(CPU.Key, TargetCPU) == 0) {
|
||||||
printf(" %-*s - This is the default target CPU"
|
Buf << " " << std::left << std::setw(MaxCPULen) << CPU.Key
|
||||||
" for the current build target (currently %s).",
|
<< " - This is the default target CPU for the current build target "
|
||||||
MaxCPULen, CPU.Key, Target->getTargetTriple().str().c_str());
|
"(currently " << Target->getTargetTriple().str() << ").";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf(" %-*s", MaxCPULen, CPU.Key);
|
Buf << " " << CPU.Key;
|
||||||
}
|
}
|
||||||
printf("\n");
|
Buf << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto &BufString = Buf.str();
|
||||||
|
Print(Out, BufString.data(), BufString.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
|
extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
|
||||||
|
|
|
@ -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_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_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
|
||||||
|
|
||||||
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
|
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
pub use crate::options::*;
|
pub use crate::options::*;
|
||||||
|
|
||||||
|
use crate::errors::FileWriteFail;
|
||||||
use crate::search_paths::SearchPath;
|
use crate::search_paths::SearchPath;
|
||||||
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
||||||
use crate::{lint, HashStableContext};
|
use crate::{lint, HashStableContext};
|
||||||
|
@ -31,6 +32,7 @@ use std::collections::btree_map::{
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fs;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf};
|
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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum PrintRequest {
|
pub enum PrintKind {
|
||||||
FileNames,
|
FileNames,
|
||||||
Sysroot,
|
Sysroot,
|
||||||
TargetLibdir,
|
TargetLibdir,
|
||||||
|
@ -855,6 +863,17 @@ impl OutFileName {
|
||||||
OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name),
|
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)]
|
#[derive(Clone, Hash, Debug, HashStable_Generic)]
|
||||||
|
@ -2005,13 +2024,7 @@ fn parse_output_types(
|
||||||
if !unstable_opts.parse_only {
|
if !unstable_opts.parse_only {
|
||||||
for list in matches.opt_strs("emit") {
|
for list in matches.opt_strs("emit") {
|
||||||
for output_type in list.split(',') {
|
for output_type in list.split(',') {
|
||||||
let (shorthand, path) = match output_type.split_once('=') {
|
let (shorthand, path) = split_out_file_name(output_type);
|
||||||
None => (output_type, None),
|
|
||||||
Some((shorthand, "-")) => (shorthand, Some(OutFileName::Stdout)),
|
|
||||||
Some((shorthand, path)) => {
|
|
||||||
(shorthand, Some(OutFileName::Real(PathBuf::from(path))))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
|
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
|
||||||
handler.early_error(format!(
|
handler.early_error(format!(
|
||||||
"unknown emission type: `{shorthand}` - expected one of: {display}",
|
"unknown emission type: `{shorthand}` - expected one of: {display}",
|
||||||
|
@ -2028,6 +2041,14 @@ fn parse_output_types(
|
||||||
OutputTypes(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(
|
fn should_override_cgus_and_disable_thinlto(
|
||||||
handler: &EarlyErrorHandler,
|
handler: &EarlyErrorHandler,
|
||||||
output_types: &OutputTypes,
|
output_types: &OutputTypes,
|
||||||
|
@ -2091,41 +2112,49 @@ fn collect_print_requests(
|
||||||
) -> Vec<PrintRequest> {
|
) -> Vec<PrintRequest> {
|
||||||
let mut prints = Vec::<PrintRequest>::new();
|
let mut prints = Vec::<PrintRequest>::new();
|
||||||
if cg.target_cpu.as_ref().is_some_and(|s| s == "help") {
|
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;
|
cg.target_cpu = None;
|
||||||
};
|
};
|
||||||
if cg.target_feature == "help" {
|
if cg.target_feature == "help" {
|
||||||
prints.push(PrintRequest::TargetFeatures);
|
prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout });
|
||||||
cg.target_feature = String::new();
|
cg.target_feature = String::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRINT_REQUESTS: &[(&str, PrintRequest)] = &[
|
const PRINT_KINDS: &[(&str, PrintKind)] = &[
|
||||||
("crate-name", PrintRequest::CrateName),
|
("crate-name", PrintKind::CrateName),
|
||||||
("file-names", PrintRequest::FileNames),
|
("file-names", PrintKind::FileNames),
|
||||||
("sysroot", PrintRequest::Sysroot),
|
("sysroot", PrintKind::Sysroot),
|
||||||
("target-libdir", PrintRequest::TargetLibdir),
|
("target-libdir", PrintKind::TargetLibdir),
|
||||||
("cfg", PrintRequest::Cfg),
|
("cfg", PrintKind::Cfg),
|
||||||
("calling-conventions", PrintRequest::CallingConventions),
|
("calling-conventions", PrintKind::CallingConventions),
|
||||||
("target-list", PrintRequest::TargetList),
|
("target-list", PrintKind::TargetList),
|
||||||
("target-cpus", PrintRequest::TargetCPUs),
|
("target-cpus", PrintKind::TargetCPUs),
|
||||||
("target-features", PrintRequest::TargetFeatures),
|
("target-features", PrintKind::TargetFeatures),
|
||||||
("relocation-models", PrintRequest::RelocationModels),
|
("relocation-models", PrintKind::RelocationModels),
|
||||||
("code-models", PrintRequest::CodeModels),
|
("code-models", PrintKind::CodeModels),
|
||||||
("tls-models", PrintRequest::TlsModels),
|
("tls-models", PrintKind::TlsModels),
|
||||||
("native-static-libs", PrintRequest::NativeStaticLibs),
|
("native-static-libs", PrintKind::NativeStaticLibs),
|
||||||
("stack-protector-strategies", PrintRequest::StackProtectorStrategies),
|
("stack-protector-strategies", PrintKind::StackProtectorStrategies),
|
||||||
("target-spec-json", PrintRequest::TargetSpec),
|
("target-spec-json", PrintKind::TargetSpec),
|
||||||
("all-target-specs-json", PrintRequest::AllTargetSpecs),
|
("all-target-specs-json", PrintKind::AllTargetSpecs),
|
||||||
("link-args", PrintRequest::LinkArgs),
|
("link-args", PrintKind::LinkArgs),
|
||||||
("split-debuginfo", PrintRequest::SplitDebuginfo),
|
("split-debuginfo", PrintKind::SplitDebuginfo),
|
||||||
("deployment-target", PrintRequest::DeploymentTarget),
|
("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| {
|
prints.extend(matches.opt_strs("print").into_iter().map(|req| {
|
||||||
match PRINT_REQUESTS.iter().find(|&&(name, _)| name == req) {
|
let (req, out) = split_out_file_name(&req);
|
||||||
Some((_, PrintRequest::TargetSpec)) => {
|
|
||||||
|
let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) {
|
||||||
|
Some((_, PrintKind::TargetSpec)) => {
|
||||||
if unstable_opts.unstable_options {
|
if unstable_opts.unstable_options {
|
||||||
PrintRequest::TargetSpec
|
PrintKind::TargetSpec
|
||||||
} else {
|
} else {
|
||||||
handler.early_error(
|
handler.early_error(
|
||||||
"the `-Z unstable-options` flag must also be passed to \
|
"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 {
|
if unstable_opts.unstable_options {
|
||||||
PrintRequest::AllTargetSpecs
|
PrintKind::AllTargetSpecs
|
||||||
} else {
|
} else {
|
||||||
handler.early_error(
|
handler.early_error(
|
||||||
"the `-Z unstable-options` flag must also be passed to \
|
"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 => {
|
None => {
|
||||||
let prints =
|
let prints =
|
||||||
PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
|
PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
|
||||||
let prints = prints.join(", ");
|
let prints = prints.join(", ");
|
||||||
handler.early_error(format!(
|
handler.early_error(format!(
|
||||||
"unknown print request `{req}`. Valid print requests are: {prints}"
|
"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
|
prints
|
||||||
|
|
|
@ -163,6 +163,13 @@ pub struct FileIsNotWriteable<'a> {
|
||||||
pub file: &'a std::path::Path,
|
pub file: &'a std::path::Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(session_file_write_fail)]
|
||||||
|
pub(crate) struct FileWriteFail<'a> {
|
||||||
|
pub path: &'a std::path::Path,
|
||||||
|
pub err: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(session_crate_name_does_not_match)]
|
#[diag(session_crate_name_does_not_match)]
|
||||||
pub struct CrateNameDoesNotMatch {
|
pub struct CrateNameDoesNotMatch {
|
||||||
|
|
|
@ -260,6 +260,10 @@ The valid types of print values are:
|
||||||
This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable
|
This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable
|
||||||
is present in the environment, or otherwise returns the variable's parsed value.
|
is present in the environment, or otherwise returns the variable's parsed value.
|
||||||
|
|
||||||
|
A filepath may optionally be specified for each requested information kind, in
|
||||||
|
the format `--print KIND=PATH`, just like for `--emit`. When a path is
|
||||||
|
specified, information will be written there instead of to stdout.
|
||||||
|
|
||||||
[conditional compilation]: ../reference/conditional-compilation.html
|
[conditional compilation]: ../reference/conditional-compilation.html
|
||||||
[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html
|
[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
include ../tools.mk
|
include ../tools.mk
|
||||||
|
|
||||||
all: default
|
all: default output_to_file
|
||||||
$(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) windows
|
$(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) windows
|
||||||
$(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) x86_64
|
$(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) x86_64
|
||||||
$(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc
|
$(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc
|
||||||
|
@ -11,6 +11,23 @@ all: default
|
||||||
$(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi=
|
$(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi=
|
||||||
$(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf
|
$(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf
|
||||||
|
|
||||||
|
output_to_file:
|
||||||
|
# Backend-independent, printed by rustc_driver_impl/src/lib.rs
|
||||||
|
$(RUSTC) --target x86_64-pc-windows-gnu --print cfg=$(TMPDIR)/cfg.txt
|
||||||
|
$(CGREP) windows < $(TMPDIR)/cfg.txt
|
||||||
|
|
||||||
|
# Printed from CodegenBackend trait impl in rustc_codegen_llvm/src/lib.rs
|
||||||
|
$(RUSTC) --print relocation-models=$(TMPDIR)/relocation-models.txt
|
||||||
|
$(CGREP) dynamic-no-pic < $(TMPDIR)/relocation-models.txt
|
||||||
|
|
||||||
|
# Printed by compiler/rustc_codegen_llvm/src/llvm_util.rs
|
||||||
|
$(RUSTC) --target wasm32-unknown-unknown --print target-features=$(TMPDIR)/target-features.txt
|
||||||
|
$(CGREP) reference-types < $(TMPDIR)/target-features.txt
|
||||||
|
|
||||||
|
# Printed by C++ code in rustc_llvm/llvm-wrapper/PassWrapper.cpp
|
||||||
|
$(RUSTC) --target wasm32-unknown-unknown --print target-cpus=$(TMPDIR)/target-cpus.txt
|
||||||
|
$(CGREP) generic < $(TMPDIR)/target-cpus.txt
|
||||||
|
|
||||||
ifdef IS_WINDOWS
|
ifdef IS_WINDOWS
|
||||||
default:
|
default:
|
||||||
$(RUSTC) --print cfg | $(CGREP) windows
|
$(RUSTC) --print cfg | $(CGREP) windows
|
||||||
|
|
4
tests/ui/codegen/target-cpus.rs
Normal file
4
tests/ui/codegen/target-cpus.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// needs-llvm-components: webassembly
|
||||||
|
// min-llvm-version: 17
|
||||||
|
// compile-flags: --print=target-cpus --target=wasm32-unknown-unknown
|
||||||
|
// check-pass
|
4
tests/ui/codegen/target-cpus.stdout
Normal file
4
tests/ui/codegen/target-cpus.stdout
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Available CPUs for this target:
|
||||||
|
bleeding-edge
|
||||||
|
generic - This is the default target CPU for the current build target (currently wasm32-unknown-unknown).
|
||||||
|
mvp
|
|
@ -1,4 +1,4 @@
|
||||||
error: pretty-print failed to write `/tmp/` due to $ERROR_MESSAGE
|
error: failed to write `/tmp/` due to $ERROR_MESSAGE
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue