Skip to content

Commit d6bc881

Browse files
committed
Fix handling of std crates for no_std targets
1 parent 5880a31 commit d6bc881

File tree

3 files changed

+106
-41
lines changed

3 files changed

+106
-41
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -449,21 +449,24 @@ fn copy_self_contained_objects(
449449
target_deps
450450
}
451451

452-
/// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.).
452+
/// Resolves standard library crates for `Std::run_make` for any build kind (like check, doc,
453+
/// build, clippy, etc.).
453454
pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
454-
let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
455+
let mut crates = run.make_run_crates(builder::Alias::Library);
456+
457+
// For no_std targets, we only want to check core and alloc
458+
// Regardless of core/alloc being selected explicitly or via the "library" default alias,
459+
// we only want to keep these two crates.
460+
// The set of no_std crates should be kept in sync with what `Builder::std_cargo` does.
461+
// Note: an alternative design would be to return an enum from this function (Default vs Subset)
462+
// of crates. However, several steps currently pass `-p <package>` even if all crates are
463+
// selected, because Cargo behaves differently in that case. To keep that behavior without
464+
// making further changes, we pre-filter the no-std crates here.
455465
let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
456-
457-
// For no_std targets, do not add any additional crates to the compilation other than what `compile::std_cargo` already adds for no_std targets.
458466
if target_is_no_std {
459-
vec![]
460-
}
461-
// If the paths include "library", build the entire standard library.
462-
else if has_alias {
463-
run.make_run_crates(builder::Alias::Library)
464-
} else {
465-
run.cargo_crates_in_set()
467+
crates.retain(|c| c == "core" || c == "alloc");
466468
}
469+
crates
467470
}
468471

469472
/// Tries to find LLVM's `compiler-rt` source directory, for building `library/profiler_builtins`.

src/bootstrap/src/core/builder/tests.rs

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ mod snapshot {
637637

638638
use crate::core::build_steps::{compile, dist, doc, test, tool};
639639
use crate::core::builder::tests::{
640-
TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args, first,
641-
host_target, render_steps, run_build,
640+
RenderConfig, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args,
641+
first, host_target, render_steps, run_build,
642642
};
643643
use crate::core::builder::{Builder, Kind, StepDescription, StepMetadata};
644644
use crate::core::config::TargetSelection;
@@ -1521,6 +1521,49 @@ mod snapshot {
15211521
steps.assert_contains(StepMetadata::test("CrateLibrustc", host));
15221522
steps.assert_contains_fuzzy(StepMetadata::build("rustc", host));
15231523
}
1524+
1525+
#[test]
1526+
fn doc_library() {
1527+
let ctx = TestCtx::new();
1528+
insta::assert_snapshot!(
1529+
ctx.config("doc")
1530+
.path("library")
1531+
.render_steps(), @r"
1532+
[build] llvm <host>
1533+
[build] rustc 0 <host> -> rustc 1 <host>
1534+
[build] rustdoc 0 <host>
1535+
[doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
1536+
");
1537+
}
1538+
1539+
#[test]
1540+
fn doc_core() {
1541+
let ctx = TestCtx::new();
1542+
insta::assert_snapshot!(
1543+
ctx.config("doc")
1544+
.path("core")
1545+
.render_steps(), @r"
1546+
[build] llvm <host>
1547+
[build] rustc 0 <host> -> rustc 1 <host>
1548+
[build] rustdoc 0 <host>
1549+
[doc] std 1 <host> crates=[core]
1550+
");
1551+
}
1552+
1553+
#[test]
1554+
fn doc_library_no_std_target() {
1555+
let ctx = TestCtx::new();
1556+
insta::assert_snapshot!(
1557+
ctx.config("doc")
1558+
.path("core")
1559+
.override_target_no_std(&host_target())
1560+
.render_steps(), @r"
1561+
[build] llvm <host>
1562+
[build] rustc 0 <host> -> rustc 1 <host>
1563+
[build] rustdoc 0 <host>
1564+
[doc] std 1 <host> crates=[core]
1565+
");
1566+
}
15241567
}
15251568

15261569
struct ExecutedSteps {
@@ -1529,7 +1572,10 @@ struct ExecutedSteps {
15291572

15301573
impl ExecutedSteps {
15311574
fn render(&self) -> String {
1532-
render_steps(&self.steps)
1575+
self.render_with(RenderConfig::default())
1576+
}
1577+
fn render_with(&self, config: RenderConfig) -> String {
1578+
render_steps(&self.steps, config)
15331579
}
15341580

15351581
#[track_caller]
@@ -1538,7 +1584,7 @@ impl ExecutedSteps {
15381584
if !self.contains(&metadata) {
15391585
panic!(
15401586
"Metadata `{}` ({metadata:?}) not found in executed steps:\n{}",
1541-
render_metadata(&metadata),
1587+
render_metadata(&metadata, &RenderConfig::default()),
15421588
self.render()
15431589
);
15441590
}
@@ -1553,7 +1599,7 @@ impl ExecutedSteps {
15531599
if !self.contains_fuzzy(&metadata) {
15541600
panic!(
15551601
"Metadata `{}` ({metadata:?}) not found in executed steps:\n{}",
1556-
render_metadata(&metadata),
1602+
render_metadata(&metadata, &RenderConfig::default()),
15571603
self.render()
15581604
);
15591605
}
@@ -1565,7 +1611,7 @@ impl ExecutedSteps {
15651611
if self.contains(&metadata) {
15661612
panic!(
15671613
"Metadata `{}` ({metadata:?}) found in executed steps (it should not be there):\n{}",
1568-
render_metadata(&metadata),
1614+
render_metadata(&metadata, &RenderConfig::default()),
15691615
self.render()
15701616
);
15711617
}
@@ -1618,14 +1664,24 @@ impl ConfigBuilder {
16181664
}
16191665
}
16201666

1667+
struct RenderConfig {
1668+
normalize_host: bool,
1669+
}
1670+
1671+
impl Default for RenderConfig {
1672+
fn default() -> Self {
1673+
Self { normalize_host: true }
1674+
}
1675+
}
1676+
16211677
/// Renders the executed bootstrap steps for usage in snapshot tests with insta.
16221678
/// Only renders certain important steps.
16231679
/// Each value in `steps` should be a tuple of (Step, step output).
16241680
///
16251681
/// The arrow in the rendered output (`X -> Y`) means `X builds Y`.
16261682
/// This is similar to the output printed by bootstrap to stdout, but here it is
16271683
/// generated purely for the purpose of tests.
1628-
fn render_steps(steps: &[ExecutedStep]) -> String {
1684+
fn render_steps(steps: &[ExecutedStep], config: RenderConfig) -> String {
16291685
steps
16301686
.iter()
16311687
.filter_map(|step| {
@@ -1635,35 +1691,35 @@ fn render_steps(steps: &[ExecutedStep]) -> String {
16351691
return None;
16361692
};
16371693

1638-
Some(render_metadata(&metadata))
1694+
Some(render_metadata(&metadata, &config))
16391695
})
16401696
.collect::<Vec<_>>()
16411697
.join("\n")
16421698
}
16431699

1644-
fn render_metadata(metadata: &StepMetadata) -> String {
1700+
fn render_metadata(metadata: &StepMetadata, config: &RenderConfig) -> String {
16451701
let mut record = format!("[{}] ", metadata.kind.as_str());
16461702
if let Some(compiler) = metadata.built_by {
1647-
write!(record, "{} -> ", render_compiler(compiler));
1703+
write!(record, "{} -> ", render_compiler(compiler, config));
16481704
}
16491705
let stage = metadata.get_stage().map(|stage| format!("{stage} ")).unwrap_or_default();
1650-
write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target));
1706+
write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target, config));
16511707
if let Some(metadata) = &metadata.metadata {
16521708
write!(record, " {metadata}");
16531709
}
16541710
record
16551711
}
16561712

1657-
fn normalize_target(target: TargetSelection) -> String {
1658-
target
1659-
.to_string()
1660-
.replace(&host_target(), "host")
1661-
.replace(TEST_TRIPLE_1, "target1")
1662-
.replace(TEST_TRIPLE_2, "target2")
1713+
fn normalize_target(target: TargetSelection, config: &RenderConfig) -> String {
1714+
let mut target = target.to_string();
1715+
if config.normalize_host {
1716+
target = target.replace(&host_target(), "host");
1717+
}
1718+
target.replace(TEST_TRIPLE_1, "target1").replace(TEST_TRIPLE_2, "target2")
16631719
}
16641720

1665-
fn render_compiler(compiler: Compiler) -> String {
1666-
format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host))
1721+
fn render_compiler(compiler: Compiler, config: &RenderConfig) -> String {
1722+
format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host, config))
16671723
}
16681724

16691725
fn host_target() -> String {

src/bootstrap/src/utils/tests/mod.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,30 @@ impl ConfigBuilder {
4848
}
4949

5050
pub fn path(mut self, path: &str) -> Self {
51-
self.args.push(path.to_string());
52-
self
51+
self.arg(path)
5352
}
5453

5554
pub fn paths(mut self, paths: &[&str]) -> Self {
56-
for path in paths {
57-
self = self.path(path);
55+
self.args(paths)
56+
}
57+
58+
pub fn arg(mut self, arg: &str) -> Self {
59+
self.args.push(arg.to_string());
60+
self
61+
}
62+
63+
pub fn args(mut self, args: &[&str]) -> Self {
64+
for arg in args {
65+
self = self.arg(arg);
5866
}
5967
self
6068
}
6169

70+
/// Set the specified target to be treated as a no_std target.
71+
pub fn override_target_no_std(mut self, target: &str) -> Self {
72+
self.args(&["--set", &format!("target.{target}.no-std=true")])
73+
}
74+
6275
pub fn hosts(mut self, targets: &[&str]) -> Self {
6376
self.args.push("--host".to_string());
6477
self.args.push(targets.join(","));
@@ -77,13 +90,6 @@ impl ConfigBuilder {
7790
self
7891
}
7992

80-
pub fn args(mut self, args: &[&str]) -> Self {
81-
for arg in args {
82-
self.args.push(arg.to_string());
83-
}
84-
self
85-
}
86-
8793
pub fn create_config(mut self) -> Config {
8894
// Run in dry-check, otherwise the test would be too slow
8995
self.args.push("--dry-run".to_string());

0 commit comments

Comments
 (0)