Add support for using cg_clif to bootstrap rustc
This commit is contained in:
parent
596b0d5027
commit
cf798c1ec6
@ -31,6 +31,7 @@ members = [
|
||||
]
|
||||
exclude = [
|
||||
"build",
|
||||
"compiler/rustc_codegen_cranelift",
|
||||
# HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
|
||||
"obj",
|
||||
]
|
||||
|
@ -22,7 +22,7 @@
|
||||
use rustc_errors::{ErrorReported, PResult};
|
||||
use rustc_feature::{find_gated_cfg, UnstableFeatures};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
|
||||
use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
|
||||
use rustc_interface::{interface, Queries};
|
||||
use rustc_lint::LintStore;
|
||||
use rustc_metadata::locator;
|
||||
@ -793,37 +793,24 @@ fn print_crate_info(
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a version string such as "0.12.0-dev".
|
||||
fn release_str() -> Option<&'static str> {
|
||||
option_env!("CFG_RELEASE")
|
||||
}
|
||||
|
||||
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
|
||||
fn commit_hash_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_HASH")
|
||||
}
|
||||
|
||||
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
|
||||
fn commit_date_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_DATE")
|
||||
}
|
||||
|
||||
/// Prints version information
|
||||
pub fn version(binary: &str, matches: &getopts::Matches) {
|
||||
let verbose = matches.opt_present("verbose");
|
||||
|
||||
println!("{} {}", binary, option_env!("CFG_VERSION").unwrap_or("unknown version"));
|
||||
println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
|
||||
|
||||
if verbose {
|
||||
fn unw(x: Option<&str>) -> &str {
|
||||
x.unwrap_or("unknown")
|
||||
}
|
||||
println!("binary: {}", binary);
|
||||
println!("commit-hash: {}", unw(commit_hash_str()));
|
||||
println!("commit-date: {}", unw(commit_date_str()));
|
||||
println!("commit-hash: {}", unw(util::commit_hash_str()));
|
||||
println!("commit-date: {}", unw(util::commit_date_str()));
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", unw(release_str()));
|
||||
get_builtin_codegen_backend("llvm")().print_version();
|
||||
println!("release: {}", unw(util::release_str()));
|
||||
if cfg!(llvm) {
|
||||
get_builtin_codegen_backend("llvm")().print_version();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1109,7 +1096,9 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
||||
}
|
||||
|
||||
if cg_flags.iter().any(|x| *x == "passes=list") {
|
||||
get_builtin_codegen_backend("llvm")().print_passes();
|
||||
if cfg!(llvm) {
|
||||
get_builtin_codegen_backend("llvm")().print_passes();
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -1237,7 +1226,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
format!("we would appreciate a bug report: {}", bug_report_url).into(),
|
||||
format!(
|
||||
"rustc {} running on {}",
|
||||
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
|
||||
util::version_str().unwrap_or("unknown_version"),
|
||||
config::host_triple()
|
||||
)
|
||||
.into(),
|
||||
|
@ -24,11 +24,13 @@
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
use std::env;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::io::{self, Write};
|
||||
use std::lazy::SyncOnceCell;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex, Once};
|
||||
#[cfg(not(parallel_compiler))]
|
||||
use std::{panic, thread};
|
||||
@ -238,7 +240,19 @@ pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
|
||||
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
|
||||
|
||||
INIT.call_once(|| {
|
||||
let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
|
||||
#[cfg(feature = "llvm")]
|
||||
const DEFAULT_CODEGEN_BACKEND: &'static str = "llvm";
|
||||
|
||||
#[cfg(not(feature = "llvm"))]
|
||||
const DEFAULT_CODEGEN_BACKEND: &'static str = "cranelift";
|
||||
|
||||
let codegen_name = sopts
|
||||
.debugging_opts
|
||||
.codegen_backend
|
||||
.as_ref()
|
||||
.map(|name| &name[..])
|
||||
.unwrap_or(DEFAULT_CODEGEN_BACKEND);
|
||||
|
||||
let backend = match codegen_name {
|
||||
filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
|
||||
codegen_name => get_builtin_codegen_backend(codegen_name),
|
||||
@ -367,15 +381,102 @@ fn current_dll_path() -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
|
||||
#[cfg(feature = "llvm")]
|
||||
{
|
||||
if backend_name == "llvm" {
|
||||
return rustc_codegen_llvm::LlvmCodegenBackend::new;
|
||||
match backend_name {
|
||||
#[cfg(feature = "llvm")]
|
||||
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
|
||||
_ => get_codegen_sysroot(backend_name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
|
||||
// For now we only allow this function to be called once as it'll dlopen a
|
||||
// few things, which seems to work best if we only do that once. In
|
||||
// general this assertion never trips due to the once guard in `get_codegen_backend`,
|
||||
// but there's a few manual calls to this function in this file we protect
|
||||
// against.
|
||||
static LOADED: AtomicBool = AtomicBool::new(false);
|
||||
assert!(
|
||||
!LOADED.fetch_or(true, Ordering::SeqCst),
|
||||
"cannot load the default codegen backend twice"
|
||||
);
|
||||
|
||||
let target = session::config::host_triple();
|
||||
let sysroot_candidates = sysroot_candidates();
|
||||
|
||||
let sysroot = sysroot_candidates
|
||||
.iter()
|
||||
.map(|sysroot| {
|
||||
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
|
||||
sysroot.join(libdir).with_file_name("codegen-backends")
|
||||
})
|
||||
.filter(|f| {
|
||||
info!("codegen backend candidate: {}", f.display());
|
||||
f.exists()
|
||||
})
|
||||
.next();
|
||||
let sysroot = sysroot.unwrap_or_else(|| {
|
||||
let candidates = sysroot_candidates
|
||||
.iter()
|
||||
.map(|p| p.display().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n* ");
|
||||
let err = format!(
|
||||
"failed to find a `codegen-backends` folder \
|
||||
in the sysroot candidates:\n* {}",
|
||||
candidates
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
});
|
||||
info!("probing {} for a codegen backend", sysroot.display());
|
||||
|
||||
let d = sysroot.read_dir().unwrap_or_else(|e| {
|
||||
let err = format!(
|
||||
"failed to load default codegen backend, couldn't \
|
||||
read `{}`: {}",
|
||||
sysroot.display(),
|
||||
e
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
});
|
||||
|
||||
let mut file: Option<PathBuf> = None;
|
||||
|
||||
let expected_name =
|
||||
format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE"));
|
||||
for entry in d.filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let filename = match path.file_name().and_then(|s| s.to_str()) {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
|
||||
continue;
|
||||
}
|
||||
let name = &filename[DLL_PREFIX.len()..filename.len() - DLL_SUFFIX.len()];
|
||||
if name != expected_name {
|
||||
continue;
|
||||
}
|
||||
if let Some(ref prev) = file {
|
||||
let err = format!(
|
||||
"duplicate codegen backends found\n\
|
||||
first: {}\n\
|
||||
second: {}\n\
|
||||
",
|
||||
prev.display(),
|
||||
path.display()
|
||||
);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
file = Some(path.clone());
|
||||
}
|
||||
|
||||
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
match file {
|
||||
Some(ref s) => load_backend_from_dylib(s),
|
||||
None => {
|
||||
let err = format!("unsupported builtin codegen backend `{}`", backend_name);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
|
||||
@ -782,3 +883,23 @@ fn visit_mac(&mut self, mac: &mut ast::MacCall) {
|
||||
noop_visit_mac(mac, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)"
|
||||
pub fn version_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VERSION")
|
||||
}
|
||||
|
||||
/// Returns a version string such as "0.12.0-dev".
|
||||
pub fn release_str() -> Option<&'static str> {
|
||||
option_env!("CFG_RELEASE")
|
||||
}
|
||||
|
||||
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
|
||||
pub fn commit_hash_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_HASH")
|
||||
}
|
||||
|
||||
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
|
||||
pub fn commit_date_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_DATE")
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ changelog-seen = 2
|
||||
|
||||
# This is an array of the codegen backends that will be compiled for the rustc
|
||||
# that's being compiled. The default is to only build the LLVM codegen backend,
|
||||
# and currently the only standard option supported is `"llvm"`
|
||||
# and currently the only standard options supported are `"llvm"` and `"cranelift"`.
|
||||
#codegen-backends = ["llvm"]
|
||||
|
||||
# Indicates whether LLD will be compiled and made available in the sysroot for
|
||||
|
@ -16,6 +16,7 @@ ignore = [
|
||||
# do not format submodules
|
||||
"library/backtrace",
|
||||
"library/stdarch",
|
||||
"compiler/rustc_codegen_cranelift",
|
||||
"src/doc/book",
|
||||
"src/doc/edition-guide",
|
||||
"src/doc/embedded-book",
|
||||
|
@ -962,8 +962,12 @@ class RustBuild(object):
|
||||
# the rust git repository is updated. Normal development usually does
|
||||
# not use vendoring, so hopefully this isn't too much of a problem.
|
||||
if self.use_vendored_sources and not os.path.exists(vendor_dir):
|
||||
run([self.cargo(), "vendor", "--sync=./src/tools/rust-analyzer/Cargo.toml"],
|
||||
verbose=self.verbose, cwd=self.rust_root)
|
||||
run([
|
||||
self.cargo(),
|
||||
"vendor",
|
||||
"--sync=./src/tools/rust-analyzer/Cargo.toml",
|
||||
"--sync=./compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
], verbose=self.verbose, cwd=self.rust_root)
|
||||
|
||||
|
||||
def bootstrap(help_triggered):
|
||||
|
@ -344,6 +344,7 @@ macro_rules! describe {
|
||||
Kind::Build => describe!(
|
||||
compile::Std,
|
||||
compile::Rustc,
|
||||
compile::CodegenBackend,
|
||||
compile::StartupObjects,
|
||||
tool::BuildManifest,
|
||||
tool::Rustbook,
|
||||
@ -370,9 +371,14 @@ macro_rules! describe {
|
||||
tool::CargoMiri,
|
||||
native::Lld
|
||||
),
|
||||
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => {
|
||||
describe!(check::Std, check::Rustc, check::Rustdoc, check::Clippy, check::Bootstrap)
|
||||
}
|
||||
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => describe!(
|
||||
check::Std,
|
||||
check::Rustc,
|
||||
check::Rustdoc,
|
||||
check::CodegenBackend,
|
||||
check::Clippy,
|
||||
check::Bootstrap
|
||||
),
|
||||
Kind::Test => describe!(
|
||||
crate::toolstate::ToolStateCheck,
|
||||
test::ExpandYamlAnchors,
|
||||
@ -630,6 +636,10 @@ fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
|
||||
self.ensure(Libdir { compiler, target })
|
||||
}
|
||||
|
||||
pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
|
||||
self.sysroot_libdir(compiler, compiler.host).with_file_name("codegen-backends")
|
||||
}
|
||||
|
||||
/// Returns the compiler's libdir where it stores the dynamic libraries that
|
||||
/// it itself links against.
|
||||
///
|
||||
@ -698,6 +708,15 @@ pub fn rustc(&self, compiler: Compiler) -> PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the paths to all of the compiler's codegen backends.
|
||||
fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
|
||||
fs::read_dir(self.sysroot_codegen_backends(compiler))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(Result::ok)
|
||||
.map(|entry| entry.path())
|
||||
}
|
||||
|
||||
pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
|
||||
self.ensure(tool::Rustdoc { compiler })
|
||||
}
|
||||
@ -762,6 +781,12 @@ pub fn cargo(
|
||||
let mut cargo = Command::new(&self.initial_cargo);
|
||||
let out_dir = self.stage_out(compiler, mode);
|
||||
|
||||
// Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
|
||||
// so we need to explicitly clear out if they've been updated.
|
||||
for backend in self.codegen_backends(compiler) {
|
||||
self.clear_if_dirty(&out_dir, &backend);
|
||||
}
|
||||
|
||||
if cmd == "doc" || cmd == "rustdoc" {
|
||||
let my_out = match mode {
|
||||
// This is the intended out directory for compiler documentation.
|
||||
@ -843,7 +868,7 @@ pub fn cargo(
|
||||
|
||||
match mode {
|
||||
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
|
||||
Mode::Rustc | Mode::ToolRustc => {
|
||||
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
|
||||
// Build proc macros both for the host and the target
|
||||
if target != compiler.host && cmd != "check" {
|
||||
cargo.arg("-Zdual-proc-macros");
|
||||
@ -904,6 +929,8 @@ pub fn cargo(
|
||||
// problem, somehow -- not really clear why -- but we know that this
|
||||
// fixes things.
|
||||
Mode::ToolRustc => metadata.push_str("tool-rustc"),
|
||||
// Same for codegen backends.
|
||||
Mode::Codegen => metadata.push_str("codegen"),
|
||||
_ => {}
|
||||
}
|
||||
cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata);
|
||||
@ -1030,7 +1057,7 @@ pub fn cargo(
|
||||
}
|
||||
|
||||
let debuginfo_level = match mode {
|
||||
Mode::Rustc => self.config.rust_debuginfo_level_rustc,
|
||||
Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc,
|
||||
Mode::Std => self.config.rust_debuginfo_level_std,
|
||||
Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => {
|
||||
self.config.rust_debuginfo_level_tools
|
||||
|
@ -1,8 +1,10 @@
|
||||
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
|
||||
|
||||
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo};
|
||||
use crate::cache::Interned;
|
||||
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
|
||||
use crate::config::TargetSelection;
|
||||
use crate::tool::{prepare_tool_cargo, SourceType};
|
||||
use crate::INTERNER;
|
||||
use crate::{
|
||||
builder::{Builder, Kind, RunConfig, ShouldRun, Step},
|
||||
Subcommand,
|
||||
@ -175,6 +177,57 @@ fn run(self, builder: &Builder<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct CodegenBackend {
|
||||
pub target: TargetSelection,
|
||||
pub backend: Interned<String>,
|
||||
}
|
||||
|
||||
impl Step for CodegenBackend {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
for &backend in &[INTERNER.intern_str("cranelift")] {
|
||||
run.builder.ensure(CodegenBackend { target: run.target, backend });
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = builder.compiler(0, builder.config.build);
|
||||
let target = self.target;
|
||||
let backend = self.backend;
|
||||
|
||||
builder.ensure(Rustc { target });
|
||||
|
||||
let mut cargo = builder.cargo(
|
||||
compiler,
|
||||
Mode::Codegen,
|
||||
SourceType::Submodule,
|
||||
target,
|
||||
cargo_subcommand(builder.kind),
|
||||
);
|
||||
cargo
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
|
||||
rustc_cargo_env(builder, &mut cargo, target);
|
||||
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&codegen_backend_stamp(builder, compiler, target, backend),
|
||||
vec![],
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tool_check_step {
|
||||
($name:ident, $path:expr, $source_type:expr) => {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
@ -281,3 +334,16 @@ fn libstd_test_stamp(
|
||||
fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||
/// compiler for the specified target and backend.
|
||||
fn codegen_backend_stamp(
|
||||
builder: &Builder<'_>,
|
||||
compiler: Compiler,
|
||||
target: TargetSelection,
|
||||
backend: Interned<String>,
|
||||
) -> PathBuf {
|
||||
builder
|
||||
.cargo_out(compiler, Mode::Codegen, target)
|
||||
.join(format!(".librustc_codegen_{}-check.stamp", backend))
|
||||
}
|
||||
|
@ -640,6 +640,144 @@ fn run(self, builder: &Builder<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct CodegenBackend {
|
||||
pub target: TargetSelection,
|
||||
pub compiler: Compiler,
|
||||
pub backend: Interned<String>,
|
||||
}
|
||||
|
||||
impl Step for CodegenBackend {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
// Only the backends specified in the `codegen-backends` entry of `config.toml` are built.
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("compiler/rustc_codegen_cranelift")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
for &backend in &run.builder.config.rust_codegen_backends {
|
||||
if backend == "llvm" {
|
||||
continue; // Already built as part of rustc
|
||||
}
|
||||
|
||||
run.builder.ensure(CodegenBackend {
|
||||
target: run.target,
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
backend,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = self.compiler;
|
||||
let target = self.target;
|
||||
let backend = self.backend;
|
||||
|
||||
builder.ensure(Rustc { compiler, target });
|
||||
|
||||
if builder.config.keep_stage.contains(&compiler.stage) {
|
||||
builder.info(
|
||||
"Warning: Using a potentially old codegen backend. \
|
||||
This may not behave well.",
|
||||
);
|
||||
// Codegen backends are linked separately from this step today, so we don't do
|
||||
// anything here.
|
||||
return;
|
||||
}
|
||||
|
||||
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
||||
if compiler_to_use != compiler {
|
||||
builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
|
||||
return;
|
||||
}
|
||||
|
||||
let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
|
||||
|
||||
let mut cargo =
|
||||
builder.cargo(compiler, Mode::Codegen, SourceType::Submodule, target, "build");
|
||||
cargo
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
|
||||
rustc_cargo_env(builder, &mut cargo, target);
|
||||
|
||||
let tmp_stamp = out_dir.join(".tmp.stamp");
|
||||
|
||||
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false);
|
||||
if builder.config.dry_run {
|
||||
return;
|
||||
}
|
||||
let mut files = files.into_iter().filter(|f| {
|
||||
let filename = f.file_name().unwrap().to_str().unwrap();
|
||||
is_dylib(filename) && filename.contains("rustc_codegen_")
|
||||
});
|
||||
let codegen_backend = match files.next() {
|
||||
Some(f) => f,
|
||||
None => panic!("no dylibs built for codegen backend?"),
|
||||
};
|
||||
if let Some(f) = files.next() {
|
||||
panic!(
|
||||
"codegen backend built two dylibs:\n{}\n{}",
|
||||
codegen_backend.display(),
|
||||
f.display()
|
||||
);
|
||||
}
|
||||
let stamp = codegen_backend_stamp(builder, compiler, target, backend);
|
||||
let codegen_backend = codegen_backend.to_str().unwrap();
|
||||
t!(fs::write(&stamp, &codegen_backend));
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the `codegen-backends` folder for a compiler that's about to be
|
||||
/// assembled as a complete compiler.
|
||||
///
|
||||
/// This will take the codegen artifacts produced by `compiler` and link them
|
||||
/// into an appropriate location for `target_compiler` to be a functional
|
||||
/// compiler.
|
||||
fn copy_codegen_backends_to_sysroot(
|
||||
builder: &Builder<'_>,
|
||||
compiler: Compiler,
|
||||
target_compiler: Compiler,
|
||||
) {
|
||||
let target = target_compiler.host;
|
||||
|
||||
// Note that this step is different than all the other `*Link` steps in
|
||||
// that it's not assembling a bunch of libraries but rather is primarily
|
||||
// moving the codegen backend into place. The codegen backend of rustc is
|
||||
// not linked into the main compiler by default but is rather dynamically
|
||||
// selected at runtime for inclusion.
|
||||
//
|
||||
// Here we're looking for the output dylib of the `CodegenBackend` step and
|
||||
// we're copying that into the `codegen-backends` folder.
|
||||
let dst = builder.sysroot_codegen_backends(target_compiler);
|
||||
t!(fs::create_dir_all(&dst));
|
||||
|
||||
if builder.config.dry_run {
|
||||
return;
|
||||
}
|
||||
|
||||
for backend in builder.config.rust_codegen_backends.iter() {
|
||||
if backend == "llvm" {
|
||||
continue; // Already built as part of rustc
|
||||
}
|
||||
|
||||
let stamp = codegen_backend_stamp(builder, compiler, target, *backend);
|
||||
let dylib = t!(fs::read_to_string(&stamp));
|
||||
let file = Path::new(&dylib);
|
||||
let filename = file.file_name().unwrap().to_str().unwrap();
|
||||
// change `librustc_codegen_cranelift-xxxxxx.so` to
|
||||
// `librustc_codegen_cranelift-release.so`
|
||||
let target_filename = {
|
||||
let dash = filename.find('-').unwrap();
|
||||
let dot = filename.find('.').unwrap();
|
||||
format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
|
||||
};
|
||||
builder.copy(&file, &dst.join(target_filename));
|
||||
}
|
||||
}
|
||||
|
||||
/// Cargo's output path for the standard library in a given stage, compiled
|
||||
/// by a particular compiler for the specified target.
|
||||
pub fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
|
||||
@ -656,6 +794,19 @@ pub fn librustc_stamp(
|
||||
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||
/// compiler for the specified target and backend.
|
||||
fn codegen_backend_stamp(
|
||||
builder: &Builder<'_>,
|
||||
compiler: Compiler,
|
||||
target: TargetSelection,
|
||||
backend: Interned<String>,
|
||||
) -> PathBuf {
|
||||
builder
|
||||
.cargo_out(compiler, Mode::Codegen, target)
|
||||
.join(format!(".librustc_codegen_{}.stamp", backend))
|
||||
}
|
||||
|
||||
pub fn compiler_file(
|
||||
builder: &Builder<'_>,
|
||||
compiler: &Path,
|
||||
@ -782,6 +933,18 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
|
||||
// when not performing a full bootstrap).
|
||||
builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
|
||||
|
||||
for &backend in builder.config.rust_codegen_backends.iter() {
|
||||
if backend == "llvm" {
|
||||
continue; // Already built as part of rustc
|
||||
}
|
||||
|
||||
builder.ensure(CodegenBackend {
|
||||
compiler: build_compiler,
|
||||
target: target_compiler.host,
|
||||
backend,
|
||||
});
|
||||
}
|
||||
|
||||
let lld_install = if builder.config.lld_enabled {
|
||||
Some(builder.ensure(native::Lld { target: target_compiler.host }))
|
||||
} else {
|
||||
@ -804,6 +967,8 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
|
||||
|
||||
let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
|
||||
if let Some(lld_install) = lld_install {
|
||||
let src_exe = exe("lld", target_compiler.host);
|
||||
|
@ -504,6 +504,19 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy over the codegen backends
|
||||
let backends_src = builder.sysroot_codegen_backends(compiler);
|
||||
let backends_rel = backends_src
|
||||
.strip_prefix(&src)
|
||||
.unwrap()
|
||||
.strip_prefix(builder.sysroot_libdir_relative(compiler))
|
||||
.unwrap();
|
||||
// Don't use custom libdir here because ^lib/ will be resolved again with installer
|
||||
let backends_dst = image.join("lib").join(&backends_rel);
|
||||
|
||||
t!(fs::create_dir_all(&backends_dst));
|
||||
builder.cp_r(&backends_src, &backends_dst);
|
||||
|
||||
// Copy libLLVM.so to the lib dir as well, if needed. While not
|
||||
// technically needed by rustc itself it's needed by lots of other
|
||||
// components like the llvm tools and LLD. LLD is included below and
|
||||
@ -1115,6 +1128,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
cmd.arg("vendor")
|
||||
.arg("--sync")
|
||||
.arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
|
||||
.arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
|
||||
.current_dir(&plain_dst_src);
|
||||
builder.run(&mut cmd);
|
||||
}
|
||||
|
@ -307,6 +307,9 @@ pub enum Mode {
|
||||
/// Build librustc, and compiler libraries, placing output in the "stageN-rustc" directory.
|
||||
Rustc,
|
||||
|
||||
/// Build a codegen backend for rustc, placing the output in the "stageN-codegen" directory.
|
||||
Codegen,
|
||||
|
||||
/// Build a tool, placing output in the "stage0-bootstrap-tools"
|
||||
/// directory. This is for miscellaneous sets of tools that are built
|
||||
/// using the bootstrap stage0 compiler in its entirety (target libraries
|
||||
@ -594,6 +597,7 @@ fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
|
||||
let suffix = match mode {
|
||||
Mode::Std => "-std",
|
||||
Mode::Rustc => "-rustc",
|
||||
Mode::Codegen => "-codegen",
|
||||
Mode::ToolBootstrap => "-bootstrap-tools",
|
||||
Mode::ToolStd | Mode::ToolRustc => "-tools",
|
||||
};
|
||||
|
@ -50,6 +50,7 @@ macro_rules! tidy_error {
|
||||
|
||||
fn filter_dirs(path: &Path) -> bool {
|
||||
let skip = [
|
||||
"compiler/rustc_codegen_cranelift",
|
||||
"src/llvm-project",
|
||||
"library/backtrace",
|
||||
"library/stdarch",
|
||||
|
Loading…
Reference in New Issue
Block a user