Skip to content
Permalink
Browse files

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.
  • Loading branch information...
alexcrichton committed May 28, 2019
1 parent ad52c77 commit f7cc467b59474dcbe9dcaf3c22dab3e663937de5
Showing with 98 additions and 98 deletions.
  1. +63 −38 src/bootstrap/builder.rs
  2. +16 −13 src/bootstrap/compile.rs
  3. +9 −8 src/bootstrap/dist.rs
  4. +5 −30 src/bootstrap/doc.rs
  5. +5 −9 src/bootstrap/test.rs
@@ -577,6 +577,25 @@ impl<'a> Builder<'a> {
})
}

/// 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 @@ impl<'a> Builder<'a> {
// 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 @@ mod __test {
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 @@ mod __test {
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,18 +1470,51 @@ mod __test {
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,
},
]
);
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 @@ mod __test {
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 @@ mod __test {
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 @@ mod __test {
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 @@ mod __test {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]
);
assert_eq!(
@@ -1718,10 +1762,6 @@ mod __test {
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 @@ mod __test {
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 @@ mod __test {
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 @@ mod __test {
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 @@ mod __test {
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 @@ impl Step for Std {

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 @@ impl Step for Test {
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 @@ impl Step for Rustc {
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 @@ impl Step for CodegenBackend {
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 @@ impl Step for Std {

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 @@ impl Step for Analysis {

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 @@ impl Step for Std {
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 @@ impl Step for Test {
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 @@ impl Step for WhitelistedRustc {
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 @@ impl Step for Rustc {
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 @@ impl Step for Rustdoc {
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");

0 comments on commit f7cc467

Please sign in to comment.
You can’t perform that action at this time.