-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support when build-std
is set for Cargo
#3078
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,3 +252,20 @@ pub fn debug_cmd(prefix: &str, verbose: usize, cmd: &Command) { | |
} | ||
eprintln!("{prefix} running command: {cmd:?}"); | ||
} | ||
|
||
/// Checks if Cargo's build-std setting is enabled for one or more crates. | ||
pub fn is_build_std_set() -> bool { | ||
let cmd = cargo() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to pass It might be worth having a little helper function that invokes |
||
// TODO: remove the -Z argument when this subcommand is stabilized; | ||
// see <https://github.com/rust-lang/cargo/issues/9301> | ||
.args(&["-Zunstable-options", "config", "get", "--format=json-value", "unstable.build-std"]) | ||
.output() | ||
.expect("failed to get Cargo config"); | ||
// TODO: Cargo will exit with an error code if the `unstable.build-std` key is not set. Should | ||
// we still return false if an unrelated error has occurred? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally we'd distinguish these cases. Which status code does cargo return when the key is absent? The least we can do is raise an error on any unexpected status code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I think Cargo returns 101 for most errors (unless I am misunderstanding your question). This includes when the key is absent but also, e.g., when the key Relevant Cargo code: https://github.com/rust-lang/cargo/blob/f5418fcfebe7d01536b891c8b2ceb32c4eaf098c/src/cargo/util/errors.rs#L324C1-L341C2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, that's unfortunate. But still you can then treat only error 101 as "absent" and all other codes as actual errors. |
||
if !cmd.status.success() { | ||
return false; | ||
} | ||
|
||
cmd.stdout.get(0..2) == Some(b"[\"") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -242,21 +242,49 @@ fn run_compiler( | |
callbacks: &mut (dyn rustc_driver::Callbacks + Send), | ||
) -> ! { | ||
if target_crate { | ||
// Miri needs a custom sysroot for target crates. | ||
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where | ||
// that sysroot lives, and that is passed to rustc. | ||
let sysroot_flag = "--sysroot"; | ||
if !args.iter().any(|e| e == sysroot_flag) { | ||
// Using the built-in default here would be plain wrong, so we *require* | ||
// the env var to make sure things make sense. | ||
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| { | ||
show_error!( | ||
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set" | ||
) | ||
}); | ||
if env::var_os("MIRI_STD_AWARE_CARGO").is_some() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would strongly prefer if we could avoid having such hacks in the Miri driver. This should all be taken care of by
|
||
let crate_name = parse_crate_name(&args).unwrap_or_else(|| { | ||
show_error!("`MIRI_STD_AWARE_CARGO` is set but `--crate-name` is not") | ||
}) | ||
.to_owned(); | ||
// This list should be kept in sync with the one from | ||
// `cargo/core/compiler/standard_lib.rs`. | ||
if matches!( | ||
crate_name.as_str(), | ||
"std" | ||
| "core" | ||
| "alloc" | ||
| "proc_macro" | ||
| "panic_abort" | ||
| "panic_unwind" | ||
| "test" | ||
| "compiler_builtins" | ||
) { | ||
// We are compiling the standard library. | ||
args.push("-Cdebug-assertions=off".into()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have also written a version of this which attempts to fix existing "-Cdebug-assertions", "-Coverflow-checks", etc. options if they are present (and also accounting for, e.g., if "-C" and "debug-assertions" are separate arguments), and only resorts to appending new arguments if the options are not present. However, I'm not sure if this extra complexity is warranted, because I think rustc can handle duplicate codegen options just fine, so probably the only benefit would be to make the rustc invocation "nicer" for someone debugging the interaction between miri and rustc There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we want this? If the user has enabled debug assertions then we should honor that. We should behave like regular Miri no longer sets |
||
args.push("-Coverflow-checks=on".into()); | ||
} | ||
// See `cargo_miri::phase_rustc`. | ||
if crate_name == "panic_abort" { | ||
args.push("-Cpanic=abort".into()); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this really needed? If build-std with regular rustc doesn't need it then we shouldn't need it either. AFAIK build-std will simply only build the panic runtime that is actually needed for this crate and this avoids the issue that comes up when building the panic runtime for a sysroot. |
||
} else { | ||
// Miri needs a custom sysroot for target crates. | ||
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where | ||
// that sysroot lives, and that is passed to rustc. | ||
let sysroot_flag = "--sysroot"; | ||
if !args.iter().any(|e| e == sysroot_flag) { | ||
// Using the built-in default here would be plain wrong, so we *require* | ||
// the env var to make sure things make sense. | ||
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| { | ||
show_error!( | ||
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set" | ||
) | ||
}); | ||
|
||
args.push(sysroot_flag.to_owned()); | ||
args.push(miri_sysroot); | ||
args.push(sysroot_flag.to_owned()); | ||
args.push(miri_sysroot); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -284,6 +312,25 @@ fn parse_comma_list<T: FromStr>(input: &str) -> Result<Vec<T>, T::Err> { | |
input.split(',').map(str::parse::<T>).collect() | ||
} | ||
|
||
/// Extracts the value associated with the `--crate-name` argument from the given command line. | ||
fn parse_crate_name(args: &Vec<String>) -> Option<&str> { | ||
let mut iter = args.iter(); | ||
while let Some(e) = iter.next() { | ||
let Some(("", tail)) = e.split_once("--crate-name") else { | ||
continue; | ||
}; | ||
if let Some(("", val)) = tail.split_once("=") { | ||
return Some(val); | ||
} else if tail == "" { | ||
return Some(iter.next().as_ref().unwrap_or_else(|| { | ||
show_error!("--crate-name is missing required argument") | ||
})); | ||
} | ||
show_error!("--crate-name argument is invalid"); | ||
} | ||
None | ||
} | ||
|
||
fn main() { | ||
let handler = EarlyErrorHandler::new(ErrorOutputType::default()); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ issue_1567 = { path = "issue-1567" } | |
issue_1691 = { path = "issue-1691" } | ||
issue_1705 = { path = "issue-1705" } | ||
issue_1760 = { path = "issue-1760" } | ||
issue_2705 = { path = "issue-2705" } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was expecting we would add something somewhere that calls |
||
issue_rust_86261 = { path = "issue-rust-86261" } | ||
|
||
[dev-dependencies] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[build] | ||
target = "ee.json" | ||
|
||
[unstable] | ||
build-std = ["core"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[package] | ||
name = "issue_2705" | ||
version = "0.1.0" | ||
authors = ["Miri Team"] | ||
edition = "2018" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"arch": "mips", | ||
"cpu": "mips2", | ||
"data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", | ||
"features": "+mips2,+soft-float", | ||
"linker-flavor": "ld.lld", | ||
"llvm-abiname": "o32", | ||
"llvm-target": "mipsel-none-elf", | ||
"max-atomic-width": 32, | ||
"os": "none", | ||
"panic-strategy": "abort", | ||
"position-independent-executables": false, | ||
"relro-level": "full", | ||
"target-c-int-width": "32", | ||
"target-endian": "little", | ||
"target-pointer-width": "32", | ||
"relocation-model": "static" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
use byteorder::{ByteOrder, LittleEndian}; | ||
|
||
pub fn use_the_dependency() { | ||
let _n = <LittleEndian as ByteOrder>::read_u32(&[1, 2, 3, 4]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you move the
cargo_cmd
logic up? This is confusing now, since thematch
has too many jobs.Also we want to call
setup
before any of the other logic here. I think this should be more like