提交 f7cc467b 编写于 作者: A Alex Crichton

rustbuild: Tweak how stage1 compilers are selected

This commit furthers the previous one to ensure that we don't build an
extra stage of the compiler in CI. A test has been added to rustbuild to
ensure that this doesn't regress, and then in debugging this test it was
hunted down that the `dist::Std` target was the one erroneously pulling
in the wrong compiler.

The `dist::Std` step was updated to instead account for the "full
bootstrap" or not flag, ensuring that the correct compiler for compiling
the final standard library was used. This was another use of the
`force_use_stage1` function which was in theory supposed to be pretty
central, so existing users were all evaluated and a new function,
`Builder::compiler_for`, was introduced. All existing users of
`force_use_stage1` have been updated to use `compiler_for`, where the
semantics of `compiler_for` are similar to that of `compiler` except
that it doesn't guarantee the presence of a sysroot for the arguments
passed (as they may be modified).

Perhaps one day we can unify `compiler` and `compiler_for`, but the
usage of `Builder::compiler` is so ubiquitous it would take quite some
time to evaluate whether each one needs the sysroot or not, so it's
hoped that can be done in parallel.
上级 ad52c77a
......@@ -577,6 +577,25 @@ pub fn compiler(&self, stage: u32, host: Interned<String>) -> Compiler {
})
}
/// Similar to `compiler`, except handles the full-bootstrap option to
/// silently use the stage1 compiler instead of a stage2 compiler if one is
/// requested.
///
/// Note that this does *not* have the side effect of creating
/// `compiler(stage, host)`, unlike `compiler` above which does have such
/// a side effect. The returned compiler here can only be used to compile
/// new artifacts, it can't be used to rely on the presence of a particular
/// sysroot.
///
/// See `force_use_stage1` for documentation on what each argument is.
pub fn compiler_for(&self, stage: u32, host: Interned<String>, target: Interned<String>) -> Compiler {
if self.build.force_use_stage1(Compiler { stage, host }, target) {
self.compiler(1, self.config.build)
} else {
self.compiler(stage, host)
}
}
pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
self.ensure(compile::Sysroot { compiler })
}
......@@ -750,11 +769,7 @@ pub fn cargo(
// This is for the original compiler, but if we're forced to use stage 1, then
// std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
// we copy the libs forward.
let cmp = if self.force_use_stage1(compiler, target) {
self.compiler(1, compiler.host)
} else {
compiler
};
let cmp = self.compiler_for(compiler.stage, compiler.host, target);
let libstd_stamp = match cmd {
"check" => check::libstd_stamp(self, cmp, target),
......@@ -1371,7 +1386,7 @@ fn dist_baseline() {
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},]
);
......@@ -1408,7 +1423,7 @@ fn dist_with_targets() {
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
......@@ -1455,11 +1470,11 @@ fn dist_with_hosts() {
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: b,
},
]
......@@ -1467,6 +1482,39 @@ fn dist_with_hosts() {
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_only_cross_host() {
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
let mut build = Build::new(configure(&["B"], &[]));
build.config.docs = false;
build.hosts = vec![b];
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
assert_eq!(
first(builder.cache.all::<dist::Rustc>()),
&[
dist::Rustc {
compiler: Compiler { host: b, stage: 2 }
},
]
);
assert_eq!(
first(builder.cache.all::<compile::Rustc>()),
&[
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
]
);
}
#[test]
fn dist_with_targets_and_hosts() {
let build = Build::new(configure(&["B"], &["C"]));
......@@ -1508,11 +1556,11 @@ fn dist_with_targets_and_hosts() {
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: b,
},
dist::Std {
......@@ -1557,11 +1605,11 @@ fn dist_with_target_flag() {
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: b,
},
dist::Std {
......@@ -1608,11 +1656,11 @@ fn dist_with_same_targets_and_hosts() {
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
compiler: Compiler { host: a, stage: 1 },
target: b,
},
]
......@@ -1662,10 +1710,6 @@ fn dist_with_same_targets_and_hosts() {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]
);
assert_eq!(
......@@ -1718,10 +1762,6 @@ fn build_default() {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
......@@ -1756,10 +1796,6 @@ fn build_default() {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
......@@ -1806,9 +1842,6 @@ fn build_with_target_flag() {
compile::Assemble {
target_compiler: Compiler { host: a, stage: 1 },
},
compile::Assemble {
target_compiler: Compiler { host: b, stage: 1 },
},
compile::Assemble {
target_compiler: Compiler { host: a, stage: 2 },
},
......@@ -1828,10 +1861,6 @@ fn build_with_target_flag() {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
......@@ -1858,10 +1887,6 @@ fn build_with_target_flag() {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
......
......@@ -70,20 +70,20 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(StartupObjects { compiler, target });
if builder.force_use_stage1(compiler, target) {
let from = builder.compiler(1, builder.config.build);
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(Std {
compiler: from,
compiler: compiler_to_use,
target,
});
builder.info(&format!("Uplifting stage1 std ({} -> {})", from.host, target));
builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target));
// Even if we're not building std this stage, the new sysroot must
// still contain the third party objects needed by various targets.
copy_third_party_objects(builder, &compiler, target);
builder.ensure(StdLink {
compiler: from,
compiler: compiler_to_use,
target_compiler: compiler,
target,
});
......@@ -402,15 +402,16 @@ fn run(self, builder: &Builder<'_>) {
return;
}
if builder.force_use_stage1(compiler, target) {
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(Test {
compiler: builder.compiler(1, builder.config.build),
compiler: compiler_to_use,
target,
});
builder.info(
&format!("Uplifting stage1 test ({} -> {})", builder.config.build, target));
builder.ensure(TestLink {
compiler: builder.compiler(1, builder.config.build),
compiler: compiler_to_use,
target_compiler: compiler,
target,
});
......@@ -527,15 +528,16 @@ fn run(self, builder: &Builder<'_>) {
return;
}
if builder.force_use_stage1(compiler, target) {
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(Rustc {
compiler: builder.compiler(1, builder.config.build),
compiler: compiler_to_use,
target,
});
builder.info(&format!("Uplifting stage1 rustc ({} -> {})",
builder.config.build, target));
builder.ensure(RustcLink {
compiler: builder.compiler(1, builder.config.build),
compiler: compiler_to_use,
target_compiler: compiler,
target,
});
......@@ -691,9 +693,10 @@ fn run(self, builder: &Builder<'_>) {
return;
}
if builder.force_use_stage1(compiler, target) {
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(CodegenBackend {
compiler: builder.compiler(1, builder.config.build),
compiler: compiler_to_use,
target,
backend,
});
......
......@@ -647,7 +647,11 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
compiler: run.builder.compiler_for(
run.builder.top_stage,
run.builder.config.build,
run.target,
),
target: run.target,
});
}
......@@ -757,13 +761,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
builder.ensure(Std { compiler, target });
// Package save-analysis from stage1 if not doing a full bootstrap, as the
// stage2 artifacts is simply copied from stage1 in that case.
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler.clone()
};
// Find the actual compiler (handling the full bootstrap option) which
// produced the save-analysis data because that data isn't copied
// through the sysroot uplifting.
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
......
......@@ -475,12 +475,7 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("Documenting stage{} std ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
let compiler = builder.compiler_for(stage, builder.config.build, target);
builder.ensure(compile::Std { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Std)
......@@ -563,12 +558,7 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("Documenting stage{} test ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
let compiler = builder.compiler_for(stage, builder.config.build, target);
// Build libstd docs so that we generate relative links
builder.ensure(Std { stage, target });
......@@ -632,12 +622,7 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
let compiler = builder.compiler_for(stage, builder.config.build, target);
// Build libstd docs so that we generate relative links
builder.ensure(Std { stage, target });
......@@ -706,12 +691,7 @@ fn run(self, builder: &Builder<'_>) {
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
let compiler = builder.compiler(stage, builder.config.build);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
let compiler = builder.compiler_for(stage, builder.config.build, target);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/librustdoc docs disabled");
......@@ -807,12 +787,7 @@ fn run(self, builder: &Builder<'_>) {
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
let compiler = builder.compiler(stage, builder.config.build);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
let compiler = builder.compiler_for(stage, builder.config.build, target);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/librustdoc docs disabled");
......
......@@ -1707,15 +1707,11 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(compile::Test { compiler, target });
builder.ensure(RemoteCopyLibs { compiler, target });
// If we're not doing a full bootstrap but we're testing a stage2 version of
// libstd, then what we're actually testing is the libstd produced in
// stage1. Reflect that here by updating the compiler that we're working
// with automatically.
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler.clone()
};
// If we're not doing a full bootstrap but we're testing a stage2
// version of libstd, then what we're actually testing is the libstd
// produced in stage1. Reflect that here by updating the compiler that
// we're working with automatically.
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
match mode {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册