Auto merge of #76415 - Mark-Simulacrum:bootstrap-cross-compilation, r=alexcrichton
rustbuild: avoid trying to inversely cross-compile for build triple from host triples This changes rustbuild's cross compilation logic to better match what users expect, particularly, avoiding trying to inverse cross-compile for the build triple from host triples. That is, if build=A, host=B, target=B, we do not want to try and compile for A from B. Indeed, the only "known to run" triple when cross-compiling is the build triple A. When testing for a particular target we need to be able to run binaries compiled for that target though. The last commit also modifies the default set of host/target triples to avoid producing needless artifacts for the build triple: The new behavior is to respect --host and --target when passed as the *only* configured triples (no triples are implicitly added). The default for --host is the build triple, and the default for --target is the host triple(s), either configured or the default build triple. Fixes #76333 r? `@alexcrichton` if possible, otherwise we'll need to hunt down a reviewer
This commit is contained in:
commit
141bb23be8
9 changed files with 99 additions and 94 deletions
|
@ -120,19 +120,18 @@
|
|||
# Defaults to host platform
|
||||
#build = "x86_64-unknown-linux-gnu"
|
||||
|
||||
# In addition to the build triple, other triples to produce full compiler
|
||||
# toolchains for. Each of these triples will be bootstrapped from the build
|
||||
# triple and then will continue to bootstrap themselves. This platform must
|
||||
# currently be able to run all of the triples provided here.
|
||||
# Which triples to produce a compiler toolchain for. Each of these triples will
|
||||
# be bootstrapped from the build triple themselves.
|
||||
#
|
||||
# Defaults to just the build triple
|
||||
#host = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
# In addition to all host triples, other triples to produce the standard library
|
||||
# for. Each host triple will be used to produce a copy of the standard library
|
||||
# for each target triple.
|
||||
# Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of
|
||||
# these triples will be bootstrapped from the build triple themselves.
|
||||
#
|
||||
# Defaults to just the build triple
|
||||
# Defaults to `host`. If you set this explicitly, you likely want to add all
|
||||
# host triples to this list as well in order for those host toolchains to be
|
||||
# able to compile programs for their native target.
|
||||
#target = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
# Use this directory to store build artifacts.
|
||||
|
|
|
@ -87,11 +87,16 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
|
|||
|
||||
pub struct RunConfig<'a> {
|
||||
pub builder: &'a Builder<'a>,
|
||||
pub host: TargetSelection,
|
||||
pub target: TargetSelection,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl RunConfig<'_> {
|
||||
pub fn build_triple(&self) -> TargetSelection {
|
||||
self.builder.build.build
|
||||
}
|
||||
}
|
||||
|
||||
struct StepDescription {
|
||||
default: bool,
|
||||
only_hosts: bool,
|
||||
|
@ -165,7 +170,6 @@ impl StepDescription {
|
|||
pathset, self.name, builder.config.exclude
|
||||
);
|
||||
}
|
||||
let hosts = &builder.hosts;
|
||||
|
||||
// Determine the targets participating in this rule.
|
||||
let targets = if self.only_hosts {
|
||||
|
@ -178,16 +182,9 @@ impl StepDescription {
|
|||
&builder.targets
|
||||
};
|
||||
|
||||
for host in hosts {
|
||||
for target in targets {
|
||||
let run = RunConfig {
|
||||
builder,
|
||||
path: pathset.path(builder),
|
||||
host: *host,
|
||||
target: *target,
|
||||
};
|
||||
(self.make_run)(run);
|
||||
}
|
||||
for target in targets {
|
||||
let run = RunConfig { builder, path: pathset.path(builder), target: *target };
|
||||
(self.make_run)(run);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,6 +217,16 @@ mod dist {
|
|||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Std>()),
|
||||
&[
|
||||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
],
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
}
|
||||
|
||||
|
@ -384,12 +394,9 @@ mod dist {
|
|||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert!(!builder.cache.all::<compile::Assemble>().is_empty());
|
||||
|
@ -399,10 +406,8 @@ mod dist {
|
|||
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -425,12 +430,9 @@ mod dist {
|
|||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -439,7 +441,6 @@ mod dist {
|
|||
compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -447,7 +448,6 @@ mod dist {
|
|||
&[
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Step for Std {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Std {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
target: run.target,
|
||||
});
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ impl Step for StartupObjects {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(StartupObjects {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
target: run.target,
|
||||
});
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ impl Step for Rustc {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustc {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
target: run.target,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -273,10 +273,8 @@ struct TomlConfig {
|
|||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
struct Build {
|
||||
build: Option<String>,
|
||||
#[serde(default)]
|
||||
host: Vec<String>,
|
||||
#[serde(default)]
|
||||
target: Vec<String>,
|
||||
host: Option<Vec<String>>,
|
||||
target: Option<Vec<String>>,
|
||||
// This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable
|
||||
build_dir: Option<String>,
|
||||
cargo: Option<String>,
|
||||
|
@ -505,11 +503,6 @@ impl Config {
|
|||
config.out = dir;
|
||||
}
|
||||
|
||||
// If --target was specified but --host wasn't specified, don't run any host-only tests.
|
||||
let has_hosts = !flags.host.is_empty();
|
||||
let has_targets = !flags.target.is_empty();
|
||||
config.skip_only_host_steps = !has_hosts && has_targets;
|
||||
|
||||
let toml = file
|
||||
.map(|file| {
|
||||
let contents = t!(fs::read_to_string(&file));
|
||||
|
@ -528,25 +521,28 @@ impl Config {
|
|||
.unwrap_or_else(TomlConfig::default);
|
||||
|
||||
let build = toml.build.clone().unwrap_or_default();
|
||||
// set by bootstrap.py
|
||||
config.hosts.push(config.build);
|
||||
for host in build.host.iter().map(|h| TargetSelection::from_user(h)) {
|
||||
if !config.hosts.contains(&host) {
|
||||
config.hosts.push(host);
|
||||
}
|
||||
}
|
||||
for target in config
|
||||
.hosts
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(build.target.iter().map(|h| TargetSelection::from_user(h)))
|
||||
{
|
||||
if !config.targets.contains(&target) {
|
||||
config.targets.push(target);
|
||||
}
|
||||
}
|
||||
config.hosts = if !flags.host.is_empty() { flags.host } else { config.hosts };
|
||||
config.targets = if !flags.target.is_empty() { flags.target } else { config.targets };
|
||||
|
||||
// If --target was specified but --host wasn't specified, don't run any host-only tests.
|
||||
let has_hosts = build.host.is_some() || flags.host.is_some();
|
||||
let has_targets = build.target.is_some() || flags.target.is_some();
|
||||
config.skip_only_host_steps = !has_hosts && has_targets;
|
||||
|
||||
config.hosts = if let Some(arg_host) = flags.host.clone() {
|
||||
arg_host
|
||||
} else if let Some(file_host) = build.host {
|
||||
file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
|
||||
} else {
|
||||
vec![config.build]
|
||||
};
|
||||
config.targets = if let Some(arg_target) = flags.target.clone() {
|
||||
arg_target
|
||||
} else if let Some(file_target) = build.target {
|
||||
file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
|
||||
} else {
|
||||
// If target is *not* configured, then default to the host
|
||||
// toolchains.
|
||||
config.hosts.clone()
|
||||
};
|
||||
|
||||
config.nodejs = build.nodejs.map(PathBuf::from);
|
||||
config.gdb = build.gdb.map(PathBuf::from);
|
||||
|
|
|
@ -605,7 +605,9 @@ impl Step for DebuggerScripts {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(DebuggerScripts {
|
||||
sysroot: run.builder.sysroot(run.builder.compiler(run.builder.top_stage, run.host)),
|
||||
sysroot: run
|
||||
.builder
|
||||
.sysroot(run.builder.compiler(run.builder.top_stage, run.build_triple())),
|
||||
host: run.target,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ pub struct Flags {
|
|||
pub stage: Option<u32>,
|
||||
pub keep_stage: Vec<u32>,
|
||||
|
||||
pub host: Vec<TargetSelection>,
|
||||
pub target: Vec<TargetSelection>,
|
||||
pub host: Option<Vec<TargetSelection>>,
|
||||
pub target: Option<Vec<TargetSelection>>,
|
||||
pub config: Option<PathBuf>,
|
||||
pub jobs: Option<u32>,
|
||||
pub cmd: Subcommand,
|
||||
|
@ -526,14 +526,26 @@ Arguments:
|
|||
.into_iter()
|
||||
.map(|j| j.parse().expect("`keep-stage` should be a number"))
|
||||
.collect(),
|
||||
host: split(&matches.opt_strs("host"))
|
||||
.into_iter()
|
||||
.map(|x| TargetSelection::from_user(&x))
|
||||
.collect::<Vec<_>>(),
|
||||
target: split(&matches.opt_strs("target"))
|
||||
.into_iter()
|
||||
.map(|x| TargetSelection::from_user(&x))
|
||||
.collect::<Vec<_>>(),
|
||||
host: if matches.opt_present("host") {
|
||||
Some(
|
||||
split(&matches.opt_strs("host"))
|
||||
.into_iter()
|
||||
.map(|x| TargetSelection::from_user(&x))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
target: if matches.opt_present("target") {
|
||||
Some(
|
||||
split(&matches.opt_strs("target"))
|
||||
.into_iter()
|
||||
.map(|x| TargetSelection::from_user(&x))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
config: cfg_file,
|
||||
jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
|
||||
cmd,
|
||||
|
|
|
@ -584,7 +584,7 @@ impl Step for RustdocTheme {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.target);
|
||||
|
||||
run.builder.ensure(RustdocTheme { compiler });
|
||||
}
|
||||
|
@ -651,7 +651,6 @@ impl Step for RustdocJSStd {
|
|||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct RustdocJSNotStd {
|
||||
pub host: TargetSelection,
|
||||
pub target: TargetSelection,
|
||||
pub compiler: Compiler,
|
||||
}
|
||||
|
@ -666,8 +665,8 @@ impl Step for RustdocJSNotStd {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
run.builder.ensure(RustdocJSNotStd { host: run.host, target: run.target, compiler });
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
|
||||
run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -688,7 +687,6 @@ impl Step for RustdocJSNotStd {
|
|||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct RustdocUi {
|
||||
pub host: TargetSelection,
|
||||
pub target: TargetSelection,
|
||||
pub compiler: Compiler,
|
||||
}
|
||||
|
@ -703,8 +701,8 @@ impl Step for RustdocUi {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
run.builder.ensure(RustdocUi { host: run.host, target: run.target, compiler });
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
|
||||
run.builder.ensure(RustdocUi { target: run.target, compiler });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -873,7 +871,7 @@ macro_rules! test_definitions {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
|
||||
|
||||
run.builder.ensure($name { compiler, target: run.target });
|
||||
}
|
||||
|
@ -1422,7 +1420,7 @@ macro_rules! test_book {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure($name {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.target),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1469,7 +1467,7 @@ impl Step for ErrorIndex {
|
|||
// error_index_generator depends on librustdoc. Use the compiler that
|
||||
// is normally used to build rustdoc for other tests (like compiletest
|
||||
// tests in src/test/rustdoc) so that it shares the same artifacts.
|
||||
let compiler = run.builder.compiler_for(run.builder.top_stage, run.host, run.host);
|
||||
let compiler = run.builder.compiler_for(run.builder.top_stage, run.target, run.target);
|
||||
run.builder.ensure(ErrorIndex { compiler });
|
||||
}
|
||||
|
||||
|
@ -1573,7 +1571,7 @@ impl Step for CrateLibrustc {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let builder = run.builder;
|
||||
let compiler = builder.compiler(builder.top_stage, run.host);
|
||||
let compiler = builder.compiler(builder.top_stage, run.build_triple());
|
||||
|
||||
for krate in builder.in_tree_crates("rustc-main") {
|
||||
if krate.path.ends_with(&run.path) {
|
||||
|
@ -1620,7 +1618,7 @@ impl Step for CrateNotDefault {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let builder = run.builder;
|
||||
let compiler = builder.compiler(builder.top_stage, run.host);
|
||||
let compiler = builder.compiler(builder.top_stage, run.build_triple());
|
||||
|
||||
let test_kind = builder.kind.into();
|
||||
|
||||
|
@ -1668,7 +1666,7 @@ impl Step for Crate {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let builder = run.builder;
|
||||
let compiler = builder.compiler(builder.top_stage, run.host);
|
||||
let compiler = builder.compiler(builder.top_stage, run.build_triple());
|
||||
|
||||
let make = |mode: Mode, krate: &CargoCrate| {
|
||||
let test_kind = builder.kind.into();
|
||||
|
@ -1808,7 +1806,7 @@ impl Step for CrateRustdoc {
|
|||
|
||||
let test_kind = builder.kind.into();
|
||||
|
||||
builder.ensure(CrateRustdoc { host: run.host, test_kind });
|
||||
builder.ensure(CrateRustdoc { host: run.target, test_kind });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -2054,7 +2052,6 @@ impl Step for Bootstrap {
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TierCheck {
|
||||
pub compiler: Compiler,
|
||||
target: TargetSelection,
|
||||
}
|
||||
|
||||
impl Step for TierCheck {
|
||||
|
@ -2067,18 +2064,19 @@ impl Step for TierCheck {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler_for(run.builder.top_stage, run.host, run.host);
|
||||
run.builder.ensure(TierCheck { compiler, target: run.host });
|
||||
let compiler =
|
||||
run.builder.compiler_for(run.builder.top_stage, run.builder.build.build, run.target);
|
||||
run.builder.ensure(TierCheck { compiler });
|
||||
}
|
||||
|
||||
/// Tests the Platform Support page in the rustc book.
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
builder.ensure(compile::Std { compiler: self.compiler, target: self.target });
|
||||
builder.ensure(compile::Std { compiler: self.compiler, target: self.compiler.host });
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
self.compiler,
|
||||
Mode::ToolRustc,
|
||||
self.target,
|
||||
Mode::ToolStd,
|
||||
self.compiler.host,
|
||||
"run",
|
||||
"src/tools/tier-check",
|
||||
SourceType::InTree,
|
||||
|
|
|
@ -469,8 +469,9 @@ impl Step for Rustdoc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder
|
||||
.ensure(Rustdoc { compiler: run.builder.compiler(run.builder.top_stage, run.host) });
|
||||
run.builder.ensure(Rustdoc {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
});
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
|
|
Loading…
Add table
Reference in a new issue