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:
Matthias Krüger 2023-07-21 06:52:28 +02:00 committed by GitHub
commit b1d1e99c22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 299 additions and 141 deletions

View file

@ -8,16 +8,17 @@ use libc::c_int;
use rustc_codegen_ssa::target_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::small_c_str::SmallCStr;
use rustc_fs_util::path_to_c_string;
use rustc_middle::bug;
use rustc_session::config::PrintRequest;
use rustc_session::config::{PrintKind, PrintRequest};
use rustc_session::Session;
use rustc_span::symbol::Symbol;
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::ptr;
use std::slice;
@ -354,7 +355,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
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 known_llvm_target_features = FxHashSet::<&'static str>::default();
let mut rustc_target_features = supported_target_features(sess)
@ -387,36 +388,48 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
.max()
.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 {
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 {
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() {
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.");
println!("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],");
println!("and may be renamed or removed in a future version of LLVM or rustc.\n");
writeln!(out, "\nUse +feature to enable a feature, or -feature to disable it.");
writeln!(out, "For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n");
writeln!(out, "Code-generation features cannot be used in cfg or #[target_feature],");
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();
let tm = create_informational_target_machine(sess);
match req {
PrintRequest::TargetCPUs => {
match req.kind {
PrintKind::TargetCPUs => {
// SAFETY generate a C compatible string from a byte slice to pass
// the target CPU name into LLVM, the lifetime of the reference is
// at least as long as the C function
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
.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));
}
unsafe {
llvm::LLVMRustPrintTargetCPUs(
tm,
cpu_cstring.as_ptr(),
callback,
&mut out as *mut &mut dyn PrintBackendInfo as *mut c_void,
);
}
}
PrintRequest::TargetFeatures => print_target_features(sess, tm),
PrintKind::TargetFeatures => print_target_features(out, sess, tm),
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
}
}