mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Introduce an ArchiveBuilderBuilder
This avoids monomorphizing all linker code for each codegen backend and will allow passing in extra information to the archive builder from the codegen backend.
This commit is contained in:
parent
90da3c6f2b
commit
7c6c7e8785
@ -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,6 +17,32 @@ enum ArchiveEntry {
|
||||
File(PathBuf),
|
||||
}
|
||||
|
||||
pub(crate) struct ArArchiveBuilderBuilder;
|
||||
|
||||
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + '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,
|
||||
use_gnu_style_archive: bool,
|
||||
@ -29,18 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
fn new(sess: &'a Session) -> Self {
|
||||
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 add_file(&mut self, file: &Path) {
|
||||
self.entries.push((
|
||||
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
|
||||
@ -48,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
fn add_archive<F>(&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<dyn FnMut(&str) -> 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();
|
||||
@ -72,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build(mut self, output: &Path) -> bool {
|
||||
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||
enum BuilderKind {
|
||||
Bsd(ar::Builder<File>),
|
||||
Gnu(ar::GnuBuilder<File>),
|
||||
@ -218,13 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
|
||||
any_members
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
use rustc_codegen_ssa::back::link::link_binary;
|
||||
|
||||
link_binary::<crate::archive::ArArchiveBuilder<'_>>(sess, &codegen_results, outputs)
|
||||
link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
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;
|
||||
@ -21,6 +21,35 @@ enum ArchiveEntry {
|
||||
File(PathBuf),
|
||||
}
|
||||
|
||||
pub struct ArArchiveBuilderBuilder;
|
||||
|
||||
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
|
||||
let config = ArchiveConfig {
|
||||
sess,
|
||||
use_native_ar: false,
|
||||
// FIXME test for linux and System V derivatives instead
|
||||
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
|
||||
};
|
||||
|
||||
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<File>)>,
|
||||
@ -30,21 +59,6 @@ pub struct ArArchiveBuilder<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
fn new(sess: &'a Session) -> Self {
|
||||
let config = ArchiveConfig {
|
||||
sess,
|
||||
use_native_ar: false,
|
||||
// FIXME test for linux and System V derivatives instead
|
||||
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
|
||||
};
|
||||
|
||||
ArArchiveBuilder {
|
||||
config,
|
||||
src_archives: vec![],
|
||||
entries: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn add_file(&mut self, file: &Path) {
|
||||
self.entries.push((
|
||||
file.file_name().unwrap().to_str().unwrap().to_string(),
|
||||
@ -52,10 +66,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
fn add_archive<F>(&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<dyn FnMut(&str) -> bool + 'static>,
|
||||
) -> std::io::Result<()> {
|
||||
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
|
||||
let archive_index = self.src_archives.len();
|
||||
|
||||
@ -75,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build(mut self, output: &Path) -> bool {
|
||||
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||
use std::process::Command;
|
||||
|
||||
fn add_file_using_ar(archive: &Path, file: &Path) {
|
||||
@ -171,13 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
|
||||
any_members
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
_sess: &Session,
|
||||
_lib_name: &str,
|
||||
_dll_imports: &[DllImport],
|
||||
_tmpdir: &Path,
|
||||
) -> PathBuf {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
@ -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::<crate::archive::ArArchiveBuilder<'_>>(
|
||||
link_binary(
|
||||
sess,
|
||||
&crate::archive::ArArchiveBuilderBuilder,
|
||||
&codegen_results,
|
||||
outputs,
|
||||
)
|
||||
|
@ -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;
|
||||
|
||||
@ -53,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) -> LlvmArchiveBuilder<'a> {
|
||||
LlvmArchiveBuilder { sess, additions: Vec::new() }
|
||||
}
|
||||
|
||||
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
|
||||
where
|
||||
F: FnMut(&str) -> bool + 'static,
|
||||
{
|
||||
fn add_archive(
|
||||
&mut self,
|
||||
archive: &Path,
|
||||
skip: Box<dyn FnMut(&str) -> 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)),
|
||||
@ -87,14 +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, output: &Path) -> bool {
|
||||
fn build(mut self: Box<Self>, 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;
|
||||
|
||||
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
|
||||
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
dll_imports: &[DllImport],
|
||||
|
@ -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::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
|
||||
link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,8 @@ pub(super) fn find_library(
|
||||
));
|
||||
}
|
||||
|
||||
pub trait ArchiveBuilder<'a> {
|
||||
fn new(sess: &'a Session) -> Self;
|
||||
|
||||
fn add_file(&mut self, path: &Path);
|
||||
|
||||
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
|
||||
where
|
||||
F: FnMut(&str) -> bool + 'static;
|
||||
|
||||
fn build(self, output: &Path) -> bool;
|
||||
pub trait ArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
|
||||
|
||||
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
|
||||
/// and returns the path on disk to that import library.
|
||||
@ -56,9 +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;
|
||||
}
|
||||
|
||||
pub trait ArchiveBuilder<'a> {
|
||||
fn add_file(&mut self, path: &Path);
|
||||
|
||||
fn add_archive(
|
||||
&mut self,
|
||||
archive: &Path,
|
||||
skip: Box<dyn FnMut(&str) -> bool + 'static>,
|
||||
) -> io::Result<()>;
|
||||
|
||||
fn build(self: Box<Self>, output: &Path) -> bool;
|
||||
}
|
||||
|
@ -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> {
|
||||
@ -102,15 +103,28 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||
CrateType::Rlib => {
|
||||
let _timer = sess.timer("link_rlib");
|
||||
info!("preparing rlib to {:?}", out_filename);
|
||||
link_rlib::<B>(sess, codegen_results, RlibFlavor::Normal, &path)?
|
||||
.build(&out_filename);
|
||||
link_rlib(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results,
|
||||
RlibFlavor::Normal,
|
||||
&path,
|
||||
)?
|
||||
.build(&out_filename);
|
||||
}
|
||||
CrateType::Staticlib => {
|
||||
link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?;
|
||||
link_staticlib(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results,
|
||||
&out_filename,
|
||||
&path,
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
link_natively::<B>(
|
||||
link_natively(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
crate_type,
|
||||
&out_filename,
|
||||
codegen_results,
|
||||
@ -240,15 +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,
|
||||
tmpdir: &MaybeTempDir,
|
||||
) -> Result<B, ErrorGuaranteed> {
|
||||
) -> Result<Box<dyn ArchiveBuilder<'a> + 'a>, ErrorGuaranteed> {
|
||||
let lib_search_paths = archive_search_paths(sess);
|
||||
|
||||
let mut ab = <B as ArchiveBuilder>::new(sess);
|
||||
let mut ab = archive_builder_builder.new_archive_builder(sess);
|
||||
|
||||
let trailing_metadata = match flavor {
|
||||
RlibFlavor::Normal => {
|
||||
@ -333,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(),
|
||||
@ -346,10 +361,14 @@ 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)?
|
||||
{
|
||||
let output_path =
|
||||
B::create_dll_import_lib(sess, &raw_dylib_name, &raw_dylib_imports, tmpdir.as_ref());
|
||||
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, |_| false).unwrap_or_else(|e| {
|
||||
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| {
|
||||
sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e));
|
||||
});
|
||||
}
|
||||
@ -442,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> {
|
||||
info!("preparing staticlib to {:?}", out_filename);
|
||||
let mut ab = link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, tempdir)?;
|
||||
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| {
|
||||
@ -483,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());
|
||||
@ -641,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,
|
||||
@ -650,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::<B>(
|
||||
let mut cmd = linker_with_args(
|
||||
&linker_path,
|
||||
flavor,
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
crate_type,
|
||||
tmpdir,
|
||||
out_filename,
|
||||
@ -1839,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,
|
||||
@ -1943,7 +1975,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||
}
|
||||
|
||||
// Upstream rust libraries and their non-bundled static libraries
|
||||
add_upstream_rust_crates::<B>(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.
|
||||
@ -1958,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,
|
||||
@ -2248,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,
|
||||
@ -2339,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::<B>(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.
|
||||
@ -2349,7 +2389,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
||||
}
|
||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static => {
|
||||
add_static_crate::<B>(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
|
||||
@ -2408,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::<B>(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
|
||||
@ -2434,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,
|
||||
@ -2476,35 +2517,38 @@ 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 = <B as ArchiveBuilder>::new(sess);
|
||||
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(&dst) {
|
||||
|
Loading…
Reference in New Issue
Block a user