Skip to content
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

Check build target supports std when building with -Zbuild-std=std #14183

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct TargetInfo {
crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,
/// `cfg` information extracted from `rustc --print=cfg`.
cfg: Vec<Cfg>,
/// `target_spec` information extracted from `rustc --print=target-spec-json`
pub target_spec: TargetSpec,
/// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
support_split_debuginfo: Vec<String>,
/// Path to the sysroot.
Expand All @@ -62,6 +64,16 @@ pub struct TargetInfo {
pub support_check_cfg: bool,
}

#[derive(Deserialize, Clone)]
pub struct Metadata {
pub std: Option<bool>,
}

#[derive(Deserialize, Clone)]
pub struct TargetSpec {
pub metadata: Metadata,
}

/// Kind of each file generated by a Unit, part of `FileType`.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum FileFlavor {
Expand Down Expand Up @@ -175,9 +187,11 @@ impl TargetInfo {
let mut process = rustc.workspace_process();
apply_env_config(gctx, &mut process)?;
process
.env("RUSTC_BOOTSTRAP", &"1".to_string())
.arg("-")
.arg("--crate-name")
.arg("___")
.arg("-Zunstable-options")
.arg("--print=file-names")
.args(&rustflags)
.env_remove("RUSTC_LOG");
Expand Down Expand Up @@ -215,6 +229,7 @@ impl TargetInfo {
process.arg("--print=sysroot");
process.arg("--print=split-debuginfo");
process.arg("--print=crate-name"); // `___` as a delimiter.
process.arg("--print=target-spec-json");
process.arg("--print=cfg");

let (output, error) = rustc
Expand Down Expand Up @@ -266,6 +281,36 @@ impl TargetInfo {
res
};

let target_spec_json = {
let mut res: String = String::new();
loop {
match lines.next() {
Some(line) if line == "}" => {
res.push_str("}");
break;
}
Some(line) => res.push_str(line.into()),
None => {
return error_missing_print_output(
"target-spec-json",
&process,
&output,
&error,
)
}
}
}
res
};

let target_spec: TargetSpec = serde_json::from_str(&target_spec_json.as_str())
.with_context(|| {
format!(
"failed to parse target spec from `rustc --print=target-spec-json`, got:\n{}",
output
)
})?;
Copy link
Member

@Noratrieb Noratrieb Jul 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please make this non-fatal, such that you just keep a None if the format doesn't match what you expect? (and probably also when not using the nightly channel, the RUSTC_BOOTSTRAP=1 is quite problematic above and should be avoided), and then avoid emitting any error in that case.


let cfg = lines
.map(|line| Ok(Cfg::from_str(line)?))
.filter(TargetInfo::not_user_specific_cfg)
Expand Down Expand Up @@ -322,6 +367,7 @@ impl TargetInfo {
Flags::Rustdoc,
)?,
cfg,
target_spec,
support_split_debuginfo,
support_check_cfg,
});
Expand Down Expand Up @@ -1026,6 +1072,11 @@ impl<'gctx> RustcTargetData<'gctx> {
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
self.target_config(kind).links_overrides.get(lib_name)
}

/// Gets the target info hashmap from the target data.
pub fn target_info(&self) -> &HashMap<CompileTarget, TargetInfo> {
&self.target_info
}
}

/// Structure used to deal with Rustdoc fingerprinting
Expand Down
12 changes: 12 additions & 0 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ pub fn resolve_std<'gctx>(
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}

// check that targets support building std
if crates.contains(&"std".to_string()) {
for (target, target_info) in target_data.target_info() {
if target_info.target_spec.metadata.std == Some(false) {
return Err(anyhow::Error::msg(format!(
"building std is not supported on this target: {:?}",
target.short_name()
)));
}
}
}

let src_path = detect_sysroot_src_path(target_data)?;
let to_patch = [
"rustc-std-workspace-core",
Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/artifact_dep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn check_with_invalid_target_triple() {
[ERROR] failed to run `rustc` to learn about target-specific information

Caused by:
process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target unknown-target-triple [..]` ([EXIT_STATUS]: 1)
process didn't exit successfully: `rustc - --crate-name ___ -Zunstable-options --print=file-names --target unknown-target-triple [..]` ([EXIT_STATUS]: 1)
--- stderr
[ERROR] Error loading target specification: Could not find specification for target "unknown-target-triple". Run `rustc --print target-list` for a list of built-in targets

Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/bad_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ fn bad_crate_type() {
[ERROR] failed to run `rustc` to learn about crate-type bad_type information

Caused by:
process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --crate-type bad_type` ([EXIT_STATUS]: 1)
process didn't exit successfully: `rustc - --crate-name ___ -Zunstable-options --print=file-names --crate-type bad_type` ([EXIT_STATUS]: 1)
--- stderr
[ERROR] unknown crate type: `bad_type`

Expand Down
4 changes: 2 additions & 2 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5199,7 +5199,7 @@ fn rustc_wrapper_queries() {
.env("RUSTC_WRAPPER", &wrapper)
.with_stderr_contains("[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]")
.with_stderr_contains(
"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]",
"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ -Zunstable-options --print[..]",
)
.run();
p.build_dir().rm_rf();
Expand All @@ -5208,7 +5208,7 @@ fn rustc_wrapper_queries() {
.env("RUSTC_WORKSPACE_WRAPPER", &wrapper)
.with_stderr_contains("[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]")
.with_stderr_contains(
"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]",
"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ -Zunstable-options --print[..]",
)
.run();
}
Expand Down
44 changes: 42 additions & 2 deletions tests/testsuite/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,17 @@ fn bad_cfg_discovery() {
}
};

if mode == "no-target-spec-json" {
return;
}
loop {
let line = lines.next().unwrap();
println!("{line}");
if line == "}" {
break;
}
}

if mode != "bad-cfg" {
panic!("unexpected");
}
Expand Down Expand Up @@ -471,10 +482,34 @@ command was: `[..]compiler[..]--crate-type [..]`

p.cargo("check")
.env("RUSTC", &funky_rustc)
.env("FUNKY_MODE", "bad-cfg")
.env("FUNKY_MODE", "no-target-spec-json")
.with_status(101)
.with_stderr(
"\
[ERROR] output of --print=target-spec-json missing when learning about target-specific information from rustc
command was: `[..]compiler[..]--crate-type [..]`

--- stdout
[..]___[..]
[..]___[..]
[..]___[..]
[..]___[..]
[..]___[..]
[..]___[..]
[..]
[..]
___

",
)
.run();

p.cargo("check")
.env("RUSTC", &funky_rustc)
.env("FUNKY_MODE", "bad-cfg")
.with_status(101)
.with_stderr_contains(
"\
[ERROR] failed to parse the cfg from `rustc --print=cfg`, got:
[..]___[..]
[..]___[..]
Expand All @@ -483,8 +518,13 @@ command was: `[..]compiler[..]--crate-type [..]`
[..]___[..]
[..]___[..]
[..]
[..],[..]
[..]
___
{
",
)
.with_stderr_contains(
"\
123


Expand Down
33 changes: 33 additions & 0 deletions tests/testsuite/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ trait BuildStd: Sized {
fn build_std(&mut self, setup: &Setup) -> &mut Self;
fn build_std_arg(&mut self, setup: &Setup, arg: &str) -> &mut Self;
fn target_host(&mut self) -> &mut Self;
fn target(&mut self, target: &str) -> &mut Self;
}

impl BuildStd for Execs {
Expand All @@ -181,6 +182,11 @@ impl BuildStd for Execs {
self.arg("--target").arg(rustc_host());
self
}

fn target(&mut self, target: &str) -> &mut Self {
self.arg("--target").arg(target);
self
}
}

#[cargo_test(build_std_mock)]
Expand Down Expand Up @@ -321,6 +327,33 @@ fn check_core() {
.run();
}

#[cargo_test(build_std_mock)]
fn test_std_on_unsupported_target() {
let setup = setup();

let p = project()
.file(
"src/main.rs",
r#"
fn main() {
println!("hello");
}
"#,
)
.build();

p.cargo("build")
.build_std(&setup)
.target("aarch64-unknown-none")
.with_status(101)
.with_stderr_data(
"\
error: building std is not supported on this target: [..]
",
)
.run();
}

#[cargo_test(build_std_mock)]
fn depend_same_as_std() {
let setup = setup();
Expand Down
Loading