From cf798c1ec65a5ec3491846777f9003fabb881b4a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 15 Oct 2020 14:23:43 +0200 Subject: [PATCH] Add support for using cg_clif to bootstrap rustc --- Cargo.toml | 1 + compiler/rustc_driver/src/lib.rs | 35 ++---- compiler/rustc_interface/src/util.rs | 135 ++++++++++++++++++++-- config.toml.example | 2 +- rustfmt.toml | 1 + src/bootstrap/bootstrap.py | 8 +- src/bootstrap/builder.rs | 37 +++++- src/bootstrap/check.rs | 68 ++++++++++- src/bootstrap/compile.rs | 165 +++++++++++++++++++++++++++ src/bootstrap/dist.rs | 14 +++ src/bootstrap/lib.rs | 4 + src/tools/tidy/src/lib.rs | 1 + 12 files changed, 432 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02794d1028b..c27e5c469cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ ] exclude = [ "build", + "compiler/rustc_codegen_cranelift", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", ] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c7fb6a55d5a..a0edf55eeb2 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -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 { } 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(), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index c1b359c7d0d..7658ffb0e3d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -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 { static mut LOAD: fn() -> Box = || 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 { } pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box { - #[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 { + // 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::>() + .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 = 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") +} diff --git a/config.toml.example b/config.toml.example index e7e37c679e5..8027d7a118f 100644 --- a/config.toml.example +++ b/config.toml.example @@ -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 diff --git a/rustfmt.toml b/rustfmt.toml index 26cdcfff2a3..2b1c516cf77 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -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", diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ce37adeb28c..0e246b652c2 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -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): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 707c1ff3efa..dc4243a76d5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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 { 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 { + 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 diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 371631154f7..443a490e342 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -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, +} + +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, +) -> PathBuf { + builder + .cargo_out(compiler, Mode::Codegen, target) + .join(format!(".librustc_codegen_{}-check.stamp", backend)) +} diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 5215ab3dd4f..ed9b9108586 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -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, +} + +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, +) -> 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); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 1887b805da1..3b7458351b1 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -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); } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 22a8e828862..6880f6e816a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -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", }; diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 19218cbd66a..cc4c43f0468 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -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",