Allow LTO for dylibs
This commit is contained in:
parent
f7f17bf220
commit
32238ce1e2
3 changed files with 33 additions and 24 deletions
|
@ -32,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
|
|||
|
||||
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
CrateType::Rlib | CrateType::ProcMacro => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,17 +73,6 @@ fn prepare_lto(
|
|||
// with either fat or thin LTO
|
||||
let mut upstream_modules = Vec::new();
|
||||
if cgcx.lto != Lto::ThinLocal {
|
||||
if cgcx.opts.cg.prefer_dynamic {
|
||||
diag_handler
|
||||
.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note(
|
||||
"only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
supported with LTO",
|
||||
)
|
||||
.emit();
|
||||
return Err(FatalError);
|
||||
}
|
||||
|
||||
// Make sure we actually can run LTO
|
||||
for crate_type in cgcx.crate_types.iter() {
|
||||
if !crate_type_allows_lto(*crate_type) {
|
||||
|
@ -92,6 +81,8 @@ fn prepare_lto(
|
|||
static library outputs",
|
||||
);
|
||||
return Err(e);
|
||||
} else if *crate_type == CrateType::Dylib {
|
||||
diag_handler.warn("LTO with dylibs may not be as effective");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
|
|||
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
|
@ -49,6 +49,7 @@ use std::ops::Deref;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::{ExitStatus, Output, Stdio};
|
||||
use std::{env, fmt, fs, io, mem, str};
|
||||
use itertools::Itertools;
|
||||
|
||||
pub fn ensure_removed(diag_handler: &Handler, path: &Path) {
|
||||
if let Err(e) = fs::remove_file(path) {
|
||||
|
@ -208,11 +209,24 @@ pub fn link_binary<'a>(
|
|||
}
|
||||
|
||||
pub fn each_linked_rlib(
|
||||
sess: &Session,
|
||||
info: &CrateInfo,
|
||||
f: &mut dyn FnMut(CrateNum, &Path),
|
||||
) -> Result<(), errors::LinkRlibError> {
|
||||
let crates = info.used_crates.iter();
|
||||
let mut fmts = None;
|
||||
|
||||
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
|
||||
if lto_active {
|
||||
for combination in info.dependency_formats.iter().combinations(2) {
|
||||
let (ty1, list1) = combination[0];
|
||||
let (ty2, list2) = combination[1];
|
||||
if list1 != list2 {
|
||||
return Err(format!("{ty1:?} and {ty2:?} do not have equivalent dependency formats (`{list1:?}` vs `{list2:?}`)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ty, list) in info.dependency_formats.iter() {
|
||||
match ty {
|
||||
CrateType::Executable
|
||||
|
@ -222,6 +236,10 @@ pub fn each_linked_rlib(
|
|||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
CrateType::Dylib if lto_active => {
|
||||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -490,7 +508,7 @@ fn link_staticlib<'a>(
|
|||
)?;
|
||||
let mut all_native_libs = vec![];
|
||||
|
||||
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
||||
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||
|
||||
|
|
|
@ -999,6 +999,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let coordinator_send = tx_to_llvm_workers;
|
||||
let sess = tcx.sess;
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
// Compute the set of symbols we need to retain when doing LTO (if we need to)
|
||||
let exported_symbols = {
|
||||
let mut exported_symbols = FxHashMap::default();
|
||||
|
@ -1020,7 +1028,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
}
|
||||
Lto::Fat | Lto::Thin => {
|
||||
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
|
||||
for &cnum in tcx.crates(()).iter() {
|
||||
for &(cnum, ref _path) in &each_linked_rlib_for_lto {
|
||||
exported_symbols.insert(cnum, copy_symbols(cnum));
|
||||
}
|
||||
Some(Arc::new(exported_symbols))
|
||||
|
@ -1040,14 +1048,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
})
|
||||
.expect("failed to spawn helper thread");
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
let ol =
|
||||
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
|
||||
// If we know that we won’t be doing codegen, create target machines without optimisation.
|
||||
|
|
Loading…
Add table
Reference in a new issue