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::io::{self, Read, Seek};
|
||||||
use std::path::{Path, PathBuf};
|
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::Session;
|
||||||
|
|
||||||
use object::read::archive::ArchiveFile;
|
use object::read::archive::ArchiveFile;
|
||||||
@ -17,6 +17,32 @@ enum ArchiveEntry {
|
|||||||
File(PathBuf),
|
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> {
|
pub(crate) struct ArArchiveBuilder<'a> {
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
use_gnu_style_archive: bool,
|
use_gnu_style_archive: bool,
|
||||||
@ -29,18 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArchiveBuilder<'a> for 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) {
|
fn add_file(&mut self, file: &Path) {
|
||||||
self.entries.push((
|
self.entries.push((
|
||||||
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
|
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<()>
|
fn add_archive(
|
||||||
where
|
&mut self,
|
||||||
F: FnMut(&str) -> bool + 'static,
|
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 read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
|
||||||
let archive = ArchiveFile::parse(&read_cache).unwrap();
|
let archive = ArchiveFile::parse(&read_cache).unwrap();
|
||||||
let archive_index = self.src_archives.len();
|
let archive_index = self.src_archives.len();
|
||||||
@ -72,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(mut self, output: &Path) -> bool {
|
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||||
enum BuilderKind {
|
enum BuilderKind {
|
||||||
Bsd(ar::Builder<File>),
|
Bsd(ar::Builder<File>),
|
||||||
Gnu(ar::GnuBuilder<File>),
|
Gnu(ar::GnuBuilder<File>),
|
||||||
@ -218,13 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
|
|
||||||
any_members
|
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> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
use rustc_codegen_ssa::back::link::link_binary;
|
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::fs::File;
|
||||||
use std::path::{Path, PathBuf};
|
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::Session;
|
||||||
|
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_session::cstore::DllImport;
|
||||||
@ -21,6 +21,35 @@ enum ArchiveEntry {
|
|||||||
File(PathBuf),
|
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> {
|
pub struct ArArchiveBuilder<'a> {
|
||||||
config: ArchiveConfig<'a>,
|
config: ArchiveConfig<'a>,
|
||||||
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
|
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
|
||||||
@ -30,21 +59,6 @@ pub struct ArArchiveBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArchiveBuilder<'a> for 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) {
|
fn add_file(&mut self, file: &Path) {
|
||||||
self.entries.push((
|
self.entries.push((
|
||||||
file.file_name().unwrap().to_str().unwrap().to_string(),
|
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<()>
|
fn add_archive(
|
||||||
where
|
&mut self,
|
||||||
F: FnMut(&str) -> bool + 'static,
|
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 mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
|
||||||
let archive_index = self.src_archives.len();
|
let archive_index = self.src_archives.len();
|
||||||
|
|
||||||
@ -75,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(mut self, output: &Path) -> bool {
|
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
fn add_file_using_ar(archive: &Path, file: &Path) {
|
fn add_file_using_ar(archive: &Path, file: &Path) {
|
||||||
@ -171,13 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
|
|
||||||
any_members
|
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> {
|
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
|
||||||
use rustc_codegen_ssa::back::link::link_binary;
|
use rustc_codegen_ssa::back::link::link_binary;
|
||||||
|
|
||||||
link_binary::<crate::archive::ArArchiveBuilder<'_>>(
|
link_binary(
|
||||||
sess,
|
sess,
|
||||||
|
&crate::archive::ArArchiveBuilderBuilder,
|
||||||
&codegen_results,
|
&codegen_results,
|
||||||
outputs,
|
outputs,
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@ use std::str;
|
|||||||
|
|
||||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
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::cstore::{DllCallingConvention, DllImport};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
@ -53,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
||||||
/// Creates a new static archive, ready for modifying the archive specified
|
fn add_archive(
|
||||||
/// by `config`.
|
&mut self,
|
||||||
fn new(sess: &'a Session) -> LlvmArchiveBuilder<'a> {
|
archive: &Path,
|
||||||
LlvmArchiveBuilder { sess, additions: Vec::new() }
|
skip: Box<dyn FnMut(&str) -> bool + 'static>,
|
||||||
}
|
) -> io::Result<()> {
|
||||||
|
|
||||||
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
|
|
||||||
where
|
|
||||||
F: FnMut(&str) -> bool + 'static,
|
|
||||||
{
|
|
||||||
let archive_ro = match ArchiveRO::open(archive) {
|
let archive_ro = match ArchiveRO::open(archive) {
|
||||||
Ok(ar) => ar,
|
Ok(ar) => ar,
|
||||||
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
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
|
/// Combine the provided files, rlibs, and native libraries into a single
|
||||||
/// `Archive`.
|
/// `Archive`.
|
||||||
fn build(mut self, output: &Path) -> bool {
|
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||||
match self.build_with_llvm(output) {
|
match self.build_with_llvm(output) {
|
||||||
Ok(any_members) => any_members,
|
Ok(any_members) => any_members,
|
||||||
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
|
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(
|
fn create_dll_import_lib(
|
||||||
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
dll_imports: &[DllImport],
|
dll_imports: &[DllImport],
|
||||||
|
@ -370,12 +370,12 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
codegen_results: CodegenResults,
|
codegen_results: CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
use crate::back::archive::LlvmArchiveBuilder;
|
use crate::back::archive::LlvmArchiveBuilderBuilder;
|
||||||
use rustc_codegen_ssa::back::link::link_binary;
|
use rustc_codegen_ssa::back::link::link_binary;
|
||||||
|
|
||||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
// This should produce either a finished executable or library.
|
// 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> {
|
pub trait ArchiveBuilderBuilder {
|
||||||
fn new(sess: &'a Session) -> Self;
|
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
|
/// 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.
|
/// 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
|
/// `linker_with_args`, which is specialized on `ArchiveBuilder` but
|
||||||
/// doesn't take or create an instance of that type.
|
/// doesn't take or create an instance of that type.
|
||||||
fn create_dll_import_lib(
|
fn create_dll_import_lib(
|
||||||
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
dll_imports: &[DllImport],
|
dll_imports: &[DllImport],
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
) -> PathBuf;
|
) -> 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::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
|
||||||
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
|
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::command::Command;
|
||||||
use super::linker::{self, Linker};
|
use super::linker::{self, Linker};
|
||||||
use super::metadata::{create_rmeta_file, MetadataPosition};
|
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
|
/// Performs the linkage portion of the compilation phase. This will generate all
|
||||||
/// of the requested outputs for this compilation session.
|
/// of the requested outputs for this compilation session.
|
||||||
pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
pub fn link_binary<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
@ -102,15 +103,28 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
|||||||
CrateType::Rlib => {
|
CrateType::Rlib => {
|
||||||
let _timer = sess.timer("link_rlib");
|
let _timer = sess.timer("link_rlib");
|
||||||
info!("preparing rlib to {:?}", out_filename);
|
info!("preparing rlib to {:?}", out_filename);
|
||||||
link_rlib::<B>(sess, codegen_results, RlibFlavor::Normal, &path)?
|
link_rlib(
|
||||||
|
sess,
|
||||||
|
archive_builder_builder,
|
||||||
|
codegen_results,
|
||||||
|
RlibFlavor::Normal,
|
||||||
|
&path,
|
||||||
|
)?
|
||||||
.build(&out_filename);
|
.build(&out_filename);
|
||||||
}
|
}
|
||||||
CrateType::Staticlib => {
|
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,
|
sess,
|
||||||
|
archive_builder_builder,
|
||||||
crate_type,
|
crate_type,
|
||||||
&out_filename,
|
&out_filename,
|
||||||
codegen_results,
|
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
|
/// 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
|
/// libraries. This is done by unzipping native libraries and inserting all of the contents into
|
||||||
/// this archive.
|
/// this archive.
|
||||||
fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
fn link_rlib<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
flavor: RlibFlavor,
|
flavor: RlibFlavor,
|
||||||
tmpdir: &MaybeTempDir,
|
tmpdir: &MaybeTempDir,
|
||||||
) -> Result<B, ErrorGuaranteed> {
|
) -> Result<Box<dyn ArchiveBuilder<'a> + 'a>, ErrorGuaranteed> {
|
||||||
let lib_search_paths = archive_search_paths(sess);
|
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 {
|
let trailing_metadata = match flavor {
|
||||||
RlibFlavor::Normal => {
|
RlibFlavor::Normal => {
|
||||||
@ -333,7 +348,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
if let Some(name) = lib.name {
|
if let Some(name) = lib.name {
|
||||||
let location =
|
let location =
|
||||||
find_library(name.as_str(), lib.verbatim.unwrap_or(false), &lib_search_paths, sess);
|
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!(
|
sess.fatal(&format!(
|
||||||
"failed to add native library {}: {}",
|
"failed to add native library {}: {}",
|
||||||
location.to_string_lossy(),
|
location.to_string_lossy(),
|
||||||
@ -346,10 +361,14 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
for (raw_dylib_name, raw_dylib_imports) in
|
for (raw_dylib_name, raw_dylib_imports) in
|
||||||
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
|
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
|
||||||
{
|
{
|
||||||
let output_path =
|
let output_path = archive_builder_builder.create_dll_import_lib(
|
||||||
B::create_dll_import_lib(sess, &raw_dylib_name, &raw_dylib_imports, tmpdir.as_ref());
|
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));
|
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
|
/// 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).
|
/// 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,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
tempdir: &MaybeTempDir,
|
tempdir: &MaybeTempDir,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
info!("preparing staticlib to {:?}", out_filename);
|
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 mut all_native_libs = vec![];
|
||||||
|
|
||||||
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
||||||
@ -483,7 +509,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
// might be also an extra name suffix
|
// might be also an extra name suffix
|
||||||
let obj_start = name.as_str().to_owned();
|
let obj_start = name.as_str().to_owned();
|
||||||
|
|
||||||
ab.add_archive(path, move |fname: &str| {
|
ab.add_archive(
|
||||||
|
path,
|
||||||
|
Box::new(move |fname: &str| {
|
||||||
// Ignore metadata files, no matter the name.
|
// Ignore metadata files, no matter the name.
|
||||||
if fname == METADATA_FILENAME {
|
if fname == METADATA_FILENAME {
|
||||||
return true;
|
return true;
|
||||||
@ -502,7 +530,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
|
|
||||||
// ok, don't skip this
|
// ok, don't skip this
|
||||||
false
|
false
|
||||||
})
|
}),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
|
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
|
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
|
||||||
/// files as well.
|
/// files as well.
|
||||||
fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
fn link_natively<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
@ -650,10 +680,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
||||||
let (linker_path, flavor) = linker_and_flavor(sess);
|
let (linker_path, flavor) = linker_and_flavor(sess);
|
||||||
let mut cmd = linker_with_args::<B>(
|
let mut cmd = linker_with_args(
|
||||||
&linker_path,
|
&linker_path,
|
||||||
flavor,
|
flavor,
|
||||||
sess,
|
sess,
|
||||||
|
archive_builder_builder,
|
||||||
crate_type,
|
crate_type,
|
||||||
tmpdir,
|
tmpdir,
|
||||||
out_filename,
|
out_filename,
|
||||||
@ -1839,10 +1870,11 @@ fn add_rpath_args(
|
|||||||
/// to the linking process as a whole.
|
/// to the linking process as a whole.
|
||||||
/// Order-independent options may still override each other in order-dependent fashion,
|
/// Order-independent options may still override each other in order-dependent fashion,
|
||||||
/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
|
/// 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,
|
path: &Path,
|
||||||
flavor: LinkerFlavor,
|
flavor: LinkerFlavor,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
out_filename: &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
|
// 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`
|
// Upstream dynamic native libraries linked with `#[link]` attributes at and `-l`
|
||||||
// command line options.
|
// command line options.
|
||||||
@ -1958,7 +1997,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
|||||||
for (raw_dylib_name, raw_dylib_imports) in
|
for (raw_dylib_name, raw_dylib_imports) in
|
||||||
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
|
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,
|
sess,
|
||||||
&raw_dylib_name,
|
&raw_dylib_name,
|
||||||
&raw_dylib_imports,
|
&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
|
/// 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).
|
/// 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,
|
cmd: &mut dyn Linker,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
tmpdir: &Path,
|
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];
|
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||||
match data[cnum.as_usize() - 1] {
|
match data[cnum.as_usize() - 1] {
|
||||||
_ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
|
_ 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
|
// compiler-builtins are always placed last to ensure that they're
|
||||||
// linked correctly.
|
// linked correctly.
|
||||||
@ -2349,7 +2389,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
}
|
}
|
||||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||||
Linkage::Static => {
|
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
|
// 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
|
// 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`
|
// was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
|
||||||
// is used)
|
// is used)
|
||||||
if let Some(cnum) = compiler_builtins {
|
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
|
// 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
|
// 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
|
// 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.
|
// 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,
|
cmd: &mut dyn Linker,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
|
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
@ -2476,8 +2517,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
let is_builtins = sess.target.no_builtins
|
let is_builtins = sess.target.no_builtins
|
||||||
|| !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
|| !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||||
|
|
||||||
let mut archive = <B as ArchiveBuilder>::new(sess);
|
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||||
if let Err(e) = archive.add_archive(cratepath, move |f| {
|
if let Err(e) = archive.add_archive(
|
||||||
|
cratepath,
|
||||||
|
Box::new(move |f| {
|
||||||
if f == METADATA_FILENAME {
|
if f == METADATA_FILENAME {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2504,7 +2547,8 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}) {
|
}),
|
||||||
|
) {
|
||||||
sess.fatal(&format!("failed to build archive from rlib: {}", e));
|
sess.fatal(&format!("failed to build archive from rlib: {}", e));
|
||||||
}
|
}
|
||||||
if archive.build(&dst) {
|
if archive.build(&dst) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user