diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index c92c105113954..b4c7909617079 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use object::read::archive::ArchiveFile; @@ -17,9 +17,34 @@ enum ArchiveEntry { File(PathBuf), } +pub(crate) struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + Box::new(ArArchiveBuilder { + sess, + use_gnu_style_archive: sess.target.archive_format == "gnu", + // FIXME fix builtin ranlib on macOS + no_builtin_ranlib: sess.target.is_like_osx, + + src_archives: vec![], + entries: vec![], + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[rustc_session::cstore::DllImport], + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); + } +} + pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, use_gnu_style_archive: bool, no_builtin_ranlib: bool, @@ -30,19 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { - ArArchiveBuilder { - sess, - dst: output.to_path_buf(), - use_gnu_style_archive: sess.target.archive_format == "gnu", - // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.is_like_osx, - - src_archives: vec![], - entries: vec![], - } - } - fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), @@ -50,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box bool + 'static>, + ) -> std::io::Result<()> { let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); let archive = ArchiveFile::parse(&read_cache).unwrap(); let archive_index = self.src_archives.len(); @@ -74,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self: Box, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder), Gnu(ar::GnuBuilder), @@ -163,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let mut builder = if self.use_gnu_style_archive { BuilderKind::Gnu( ar::GnuBuilder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -178,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } else { BuilderKind::Bsd( ar::Builder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -209,7 +222,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // Run ranlib to be able to link the archive let status = std::process::Command::new(ranlib) - .arg(self.dst) + .arg(output) .status() .expect("Couldn't run ranlib"); @@ -220,17 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn sess(&self) -> &Session { - self.sess - } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &Path, - ) -> PathBuf { - bug!("creating dll imports is not supported"); - } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 568bb20a3f4a7..bb0793b1deb2e 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>(sess, &codegen_results, outputs) + link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 21f62a6b0096a..f863abdcc97ec 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -1,14 +1,13 @@ use std::fs::File; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use rustc_session::cstore::DllImport; struct ArchiveConfig<'a> { sess: &'a Session, - dst: PathBuf, use_native_ar: bool, use_gnu_style_archive: bool, } @@ -22,31 +21,44 @@ enum ArchiveEntry { File(PathBuf), } -pub struct ArArchiveBuilder<'a> { - config: ArchiveConfig<'a>, - src_archives: Vec<(PathBuf, ar::Archive)>, - // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at - // the end of an archive for linkers to not get confused. - entries: Vec<(String, ArchiveEntry)>, -} +pub struct ArArchiveBuilderBuilder; -impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { let config = ArchiveConfig { sess, - dst: output.to_path_buf(), use_native_ar: false, // FIXME test for linux and System V derivatives instead use_gnu_style_archive: sess.target.options.archive_format == "gnu", }; - ArArchiveBuilder { + Box::new(ArArchiveBuilder { config, src_archives: vec![], entries: vec![], - } + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[DllImport], + _tmpdir: &Path, + ) -> PathBuf { + unimplemented!(); } +} +pub struct ArArchiveBuilder<'a> { + config: ArchiveConfig<'a>, + src_archives: Vec<(PathBuf, ar::Archive)>, + // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at + // the end of an archive for linkers to not get confused. + entries: Vec<(String, ArchiveEntry)>, +} + +impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string(), @@ -54,10 +66,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box bool + 'static>, + ) -> std::io::Result<()> { let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?); let archive_index = self.src_archives.len(); @@ -77,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self: Box, output: &Path) -> bool { use std::process::Command; fn add_file_using_ar(archive: &Path, file: &Path) { @@ -97,17 +110,17 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } let mut builder = if self.config.use_native_ar { - BuilderKind::NativeAr(&self.config.dst) + BuilderKind::NativeAr(output) } else if self.config.use_gnu_style_archive { BuilderKind::Gnu(ar::GnuBuilder::new( - File::create(&self.config.dst).unwrap(), + File::create(output).unwrap(), self.entries .iter() .map(|(name, _)| name.as_bytes().to_vec()) .collect(), )) } else { - BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap())) + BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap())) }; let any_members = !self.entries.is_empty(); @@ -164,10 +177,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { std::mem::drop(builder); // Run ranlib to be able to link the archive - let status = std::process::Command::new("ranlib") - .arg(self.config.dst) - .status() - .expect("Couldn't run ranlib"); + let status = + std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); if !status.success() { self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code())); @@ -175,17 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn sess(&self) -> &Session { - self.config.sess - } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[DllImport], - _tmpdir: &Path, - ) -> PathBuf { - unimplemented!(); - } } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index c21e0c5a35b80..8a206c0368fcb 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -133,8 +133,9 @@ impl CodegenBackend for GccCodegenBackend { fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>( + link_binary( sess, + &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs, ) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index baa858709a0c6..27039cda25382 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -10,7 +10,7 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::cstore::{DllCallingConvention, DllImport}; use rustc_session::Session; @@ -18,7 +18,6 @@ use rustc_session::Session; #[must_use = "must call build() to finish building the archive"] pub struct LlvmArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, additions: Vec, } @@ -54,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { } impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { - /// Creates a new static archive, ready for modifying the archive specified - /// by `config`. - fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> { - LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() } - } - - fn add_archive(&mut self, archive: &Path, skip: F) -> io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive: &Path, + skip: Box bool + 'static>, + ) -> io::Result<()> { let archive_ro = match ArchiveRO::open(archive) { Ok(ar) => ar, Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), @@ -88,18 +82,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { /// Combine the provided files, rlibs, and native libraries into a single /// `Archive`. - fn build(mut self) -> bool { - match self.build_with_llvm() { + fn build(mut self: Box, output: &Path) -> bool { + match self.build_with_llvm(output) { Ok(any_members) => any_members, Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)), } } +} + +pub struct LlvmArchiveBuilderBuilder; - fn sess(&self) -> &Session { - self.sess +impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) } fn create_dll_import_lib( + &self, sess: &Session, lib_name: &str, dll_imports: &[DllImport], @@ -241,7 +240,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { } impl<'a> LlvmArchiveBuilder<'a> { - fn build_with_llvm(&mut self) -> io::Result { + fn build_with_llvm(&mut self, output: &Path) -> io::Result { let kind = &*self.sess.target.archive_format; let kind = kind.parse::().map_err(|_| kind).unwrap_or_else(|kind| { self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)) @@ -251,7 +250,7 @@ impl<'a> LlvmArchiveBuilder<'a> { let mut strings = Vec::new(); let mut members = Vec::new(); - let dst = CString::new(self.dst.to_str().unwrap())?; + let dst = CString::new(output.to_str().unwrap())?; unsafe { for addition in &mut additions { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 25ce1cef9440f..eeb1ed61f288f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -370,12 +370,12 @@ impl CodegenBackend for LlvmCodegenBackend { codegen_results: CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { - use crate::back::archive::LlvmArchiveBuilder; + use crate::back::archive::LlvmArchiveBuilderBuilder; use rustc_codegen_ssa::back::link::link_binary; // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary::>(sess, &codegen_results, outputs) + link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 53550b049db09..0d2aa483d3d4a 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,4 +1,3 @@ -use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_session::cstore::DllImport; use rustc_session::Session; @@ -40,18 +39,8 @@ pub(super) fn find_library( )); } -pub trait ArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self; - - fn add_file(&mut self, path: &Path); - - fn add_archive(&mut self, archive: &Path, skip: F) -> io::Result<()> - where - F: FnMut(&str) -> bool + 'static; - - fn build(self) -> bool; - - fn sess(&self) -> &Session; +pub trait ArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a>; /// Creates a DLL Import Library . /// and returns the path on disk to that import library. @@ -59,29 +48,22 @@ pub trait ArchiveBuilder<'a> { /// `linker_with_args`, which is specialized on `ArchiveBuilder` but /// doesn't take or create an instance of that type. fn create_dll_import_lib( + &self, sess: &Session, lib_name: &str, dll_imports: &[DllImport], tmpdir: &Path, ) -> PathBuf; +} - /// Creates a DLL Import Library - /// and adds it to the current compilation's set of archives. - fn inject_dll_import_lib( +pub trait ArchiveBuilder<'a> { + fn add_file(&mut self, path: &Path); + + fn add_archive( &mut self, - lib_name: &str, - dll_imports: &[DllImport], - tmpdir: &MaybeTempDir, - ) { - let output_path = - Self::create_dll_import_lib(self.sess(), lib_name, dll_imports, tmpdir.as_ref()); + archive: &Path, + skip: Box bool + 'static>, + ) -> io::Result<()>; - self.add_archive(&output_path, |_| false).unwrap_or_else(|e| { - self.sess().fatal(&format!( - "failed to add native library {}: {}", - output_path.display(), - e - )); - }); - } + fn build(self: Box, output: &Path) -> bool; } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f0d320c7c21c9..7e6a5f0366a79 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -24,7 +24,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; -use super::archive::{find_library, ArchiveBuilder}; +use super::archive::{find_library, ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{create_rmeta_file, MetadataPosition}; @@ -56,8 +56,9 @@ pub fn ensure_removed(diag_handler: &Handler, path: &Path) { /// Performs the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. -pub fn link_binary<'a, B: ArchiveBuilder<'a>>( +pub fn link_binary<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { @@ -101,21 +102,29 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); - link_rlib::( + info!("preparing rlib to {:?}", out_filename); + link_rlib( sess, + archive_builder_builder, codegen_results, RlibFlavor::Normal, - &out_filename, &path, )? - .build(); + .build(&out_filename); } CrateType::Staticlib => { - link_staticlib::(sess, codegen_results, &out_filename, &path)?; + link_staticlib( + sess, + archive_builder_builder, + codegen_results, + &out_filename, + &path, + )?; } _ => { - link_natively::( + link_natively( sess, + archive_builder_builder, crate_type, &out_filename, codegen_results, @@ -245,18 +254,16 @@ pub fn each_linked_rlib( /// the object file of the crate, but it also contains all of the object files from native /// libraries. This is done by unzipping native libraries and inserting all of the contents into /// this archive. -fn link_rlib<'a, B: ArchiveBuilder<'a>>( +fn link_rlib<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, flavor: RlibFlavor, - out_filename: &Path, tmpdir: &MaybeTempDir, -) -> Result { - info!("preparing rlib to {:?}", out_filename); - +) -> Result + 'a>, ErrorGuaranteed> { let lib_search_paths = archive_search_paths(sess); - let mut ab = ::new(sess, out_filename); + let mut ab = archive_builder_builder.new_archive_builder(sess); let trailing_metadata = match flavor { RlibFlavor::Normal => { @@ -341,7 +348,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( if let Some(name) = lib.name { let location = find_library(name.as_str(), lib.verbatim.unwrap_or(false), &lib_search_paths, sess); - ab.add_archive(&location, |_| false).unwrap_or_else(|e| { + ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| { sess.fatal(&format!( "failed to add native library {}: {}", location.to_string_lossy(), @@ -354,7 +361,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( for (raw_dylib_name, raw_dylib_imports) in collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { - ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); + let output_path = archive_builder_builder.create_dll_import_lib( + sess, + &raw_dylib_name, + &raw_dylib_imports, + tmpdir.as_ref(), + ); + + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| { + sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e)); + }); } if let Some(trailing_metadata) = trailing_metadata { @@ -445,14 +461,21 @@ fn collate_raw_dylibs( /// /// There's no need to include metadata in a static archive, so ensure to not link in the metadata /// object file (and also don't prepare the archive with a metadata file). -fn link_staticlib<'a, B: ArchiveBuilder<'a>>( +fn link_staticlib<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, out_filename: &Path, tempdir: &MaybeTempDir, ) -> Result<(), ErrorGuaranteed> { - let mut ab = - link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?; + info!("preparing staticlib to {:?}", out_filename); + let mut ab = link_rlib( + sess, + archive_builder_builder, + codegen_results, + RlibFlavor::StaticlibBase, + tempdir, + )?; let mut all_native_libs = vec![]; let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { @@ -486,26 +509,29 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( // might be also an extra name suffix let obj_start = name.as_str().to_owned(); - ab.add_archive(path, move |fname: &str| { - // Ignore metadata files, no matter the name. - if fname == METADATA_FILENAME { - return true; - } + ab.add_archive( + path, + Box::new(move |fname: &str| { + // Ignore metadata files, no matter the name. + if fname == METADATA_FILENAME { + return true; + } - // Don't include Rust objects if LTO is enabled - if lto && looks_like_rust_object_file(fname) { - return true; - } + // Don't include Rust objects if LTO is enabled + if lto && looks_like_rust_object_file(fname) { + return true; + } - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { - return true; - } + // Otherwise if this is *not* a rust object and we're skipping + // objects then skip this file + if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { + return true; + } - // ok, don't skip this - false - }) + // ok, don't skip this + false + }), + ) .unwrap(); all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); @@ -514,7 +540,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( sess.fatal(&e); } - ab.build(); + ab.build(out_filename); if !all_native_libs.is_empty() { if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) { @@ -644,8 +670,9 @@ fn link_dwarf_object<'a>( /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream /// files as well. -fn link_natively<'a, B: ArchiveBuilder<'a>>( +fn link_natively<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, crate_type: CrateType, out_filename: &Path, codegen_results: &CodegenResults, @@ -653,10 +680,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( ) -> Result<(), ErrorGuaranteed> { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); - let mut cmd = linker_with_args::( + let mut cmd = linker_with_args( &linker_path, flavor, sess, + archive_builder_builder, crate_type, tmpdir, out_filename, @@ -1842,10 +1870,11 @@ fn add_rpath_args( /// to the linking process as a whole. /// Order-independent options may still override each other in order-dependent fashion, /// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`. -fn linker_with_args<'a, B: ArchiveBuilder<'a>>( +fn linker_with_args<'a>( path: &Path, flavor: LinkerFlavor, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, crate_type: CrateType, tmpdir: &Path, out_filename: &Path, @@ -1946,7 +1975,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( } // Upstream rust libraries and their non-bundled static libraries - add_upstream_rust_crates::(cmd, sess, codegen_results, crate_type, tmpdir); + add_upstream_rust_crates( + cmd, + sess, + archive_builder_builder, + codegen_results, + crate_type, + tmpdir, + ); // Upstream dynamic native libraries linked with `#[link]` attributes at and `-l` // command line options. @@ -1961,7 +1997,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( for (raw_dylib_name, raw_dylib_imports) in collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { - cmd.add_object(&B::create_dll_import_lib( + cmd.add_object(&archive_builder_builder.create_dll_import_lib( sess, &raw_dylib_name, &raw_dylib_imports, @@ -2251,9 +2287,10 @@ fn add_local_native_libraries( /// /// Rust crates are not considered at all when creating an rlib output. All dependencies will be /// linked when producing the final output (instead of the intermediate rlib version). -fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( +fn add_upstream_rust_crates<'a>( cmd: &mut dyn Linker, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, crate_type: CrateType, tmpdir: &Path, @@ -2342,7 +2379,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let src = &codegen_results.crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { - add_static_crate::(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); } // compiler-builtins are always placed last to ensure that they're // linked correctly. @@ -2352,7 +2389,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - add_static_crate::(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); // Link static native libs with "-bundle" modifier only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically @@ -2411,7 +2448,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic` // is used) if let Some(cnum) = compiler_builtins { - add_static_crate::(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); } // Converts a library file-stem into a cc -l argument @@ -2437,9 +2474,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // Note, however, that if we're not doing LTO we can just pass the rlib // blindly to the linker (fast) because it's fine if it's not actually // included as we're at the end of the dependency chain. - fn add_static_crate<'a, B: ArchiveBuilder<'a>>( + fn add_static_crate<'a>( cmd: &mut dyn Linker, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, tmpdir: &Path, cnum: CrateNum, @@ -2479,38 +2517,41 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let is_builtins = sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); - let mut archive = ::new(sess, &dst); - if let Err(e) = archive.add_archive(cratepath, move |f| { - if f == METADATA_FILENAME { - return true; - } + let mut archive = archive_builder_builder.new_archive_builder(sess); + if let Err(e) = archive.add_archive( + cratepath, + Box::new(move |f| { + if f == METADATA_FILENAME { + return true; + } - let canonical = f.replace('-', "_"); + let canonical = f.replace('-', "_"); - let is_rust_object = - canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); + let is_rust_object = + canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); - // If we've been requested to skip all native object files - // (those not generated by the rust compiler) then we can skip - // this file. See above for why we may want to do this. - let skip_because_cfg_say_so = skip_native && !is_rust_object; + // If we've been requested to skip all native object files + // (those not generated by the rust compiler) then we can skip + // this file. See above for why we may want to do this. + let skip_because_cfg_say_so = skip_native && !is_rust_object; - // If we're performing LTO and this is a rust-generated object - // file, then we don't need the object file as it's part of the - // LTO module. Note that `#![no_builtins]` is excluded from LTO, - // though, so we let that object file slide. - let skip_because_lto = - upstream_rust_objects_already_included && is_rust_object && is_builtins; + // If we're performing LTO and this is a rust-generated object + // file, then we don't need the object file as it's part of the + // LTO module. Note that `#![no_builtins]` is excluded from LTO, + // though, so we let that object file slide. + let skip_because_lto = + upstream_rust_objects_already_included && is_rust_object && is_builtins; - if skip_because_cfg_say_so || skip_because_lto { - return true; - } + if skip_because_cfg_say_so || skip_because_lto { + return true; + } - false - }) { + false + }), + ) { sess.fatal(&format!("failed to build archive from rlib: {}", e)); } - if archive.build() { + if archive.build(&dst) { link_upstream(&dst); } });