Auto merge of #106224 - bjorn3:staticlib_fixes, r=wesleywiser
Small fixes for --crate-type staticlib The first commit doesn't have an effect until we start translating error messages. The second commit fixes potential linker errors when combining `--crate-type staticlib` with another crate type and I think `-Cprefer-dynamic`.
This commit is contained in:
commit
d9e317a176
@ -11,7 +11,7 @@
|
|||||||
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
|
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
|
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_session::cstore::DllImport;
|
||||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||||
@ -208,16 +208,16 @@ pub fn link_binary<'a>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crate type is not passed when calculating the dylibs to include for LTO. In that case all
|
||||||
|
// crate types must use the same dependency formats.
|
||||||
pub fn each_linked_rlib(
|
pub fn each_linked_rlib(
|
||||||
sess: &Session,
|
|
||||||
info: &CrateInfo,
|
info: &CrateInfo,
|
||||||
|
crate_type: Option<CrateType>,
|
||||||
f: &mut dyn FnMut(CrateNum, &Path),
|
f: &mut dyn FnMut(CrateNum, &Path),
|
||||||
) -> Result<(), errors::LinkRlibError> {
|
) -> Result<(), errors::LinkRlibError> {
|
||||||
let crates = info.used_crates.iter();
|
let crates = info.used_crates.iter();
|
||||||
let mut fmts = None;
|
|
||||||
|
|
||||||
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
|
let fmts = if crate_type.is_none() {
|
||||||
if lto_active {
|
|
||||||
for combination in info.dependency_formats.iter().combinations(2) {
|
for combination in info.dependency_formats.iter().combinations(2) {
|
||||||
let (ty1, list1) = &combination[0];
|
let (ty1, list1) = &combination[0];
|
||||||
let (ty2, list2) = &combination[1];
|
let (ty2, list2) = &combination[1];
|
||||||
@ -230,27 +230,23 @@ pub fn each_linked_rlib(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if info.dependency_formats.is_empty() {
|
||||||
|
return Err(errors::LinkRlibError::MissingFormat);
|
||||||
for (ty, list) in info.dependency_formats.iter() {
|
|
||||||
match ty {
|
|
||||||
CrateType::Executable
|
|
||||||
| CrateType::Staticlib
|
|
||||||
| CrateType::Cdylib
|
|
||||||
| CrateType::ProcMacro => {
|
|
||||||
fmts = Some(list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CrateType::Dylib if lto_active => {
|
|
||||||
fmts = Some(list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
&info.dependency_formats[0].1
|
||||||
let Some(fmts) = fmts else {
|
} else {
|
||||||
return Err(errors::LinkRlibError::MissingFormat);
|
let fmts = info
|
||||||
|
.dependency_formats
|
||||||
|
.iter()
|
||||||
|
.find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None });
|
||||||
|
|
||||||
|
let Some(fmts) = fmts else {
|
||||||
|
return Err(errors::LinkRlibError::MissingFormat);
|
||||||
|
};
|
||||||
|
|
||||||
|
fmts
|
||||||
};
|
};
|
||||||
|
|
||||||
for &cnum in crates {
|
for &cnum in crates {
|
||||||
match fmts.get(cnum.as_usize() - 1) {
|
match fmts.get(cnum.as_usize() - 1) {
|
||||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||||
@ -516,64 +512,71 @@ fn link_staticlib<'a>(
|
|||||||
)?;
|
)?;
|
||||||
let mut all_native_libs = vec![];
|
let mut all_native_libs = vec![];
|
||||||
|
|
||||||
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
let res = each_linked_rlib(
|
||||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
&codegen_results.crate_info,
|
||||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
Some(CrateType::Staticlib),
|
||||||
|
&mut |cnum, path| {
|
||||||
|
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||||
|
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||||
|
|
||||||
// Here when we include the rlib into our staticlib we need to make a
|
// Here when we include the rlib into our staticlib we need to make a
|
||||||
// decision whether to include the extra object files along the way.
|
// decision whether to include the extra object files along the way.
|
||||||
// These extra object files come from statically included native
|
// These extra object files come from statically included native
|
||||||
// libraries, but they may be cfg'd away with #[link(cfg(..))].
|
// libraries, but they may be cfg'd away with #[link(cfg(..))].
|
||||||
//
|
//
|
||||||
// This unstable feature, though, only needs liblibc to work. The only
|
// This unstable feature, though, only needs liblibc to work. The only
|
||||||
// use case there is where musl is statically included in liblibc.rlib,
|
// use case there is where musl is statically included in liblibc.rlib,
|
||||||
// so if we don't want the included version we just need to skip it. As
|
// so if we don't want the included version we just need to skip it. As
|
||||||
// a result the logic here is that if *any* linked library is cfg'd away
|
// a result the logic here is that if *any* linked library is cfg'd away
|
||||||
// we just skip all object files.
|
// we just skip all object files.
|
||||||
//
|
//
|
||||||
// Clearly this is not sufficient for a general purpose feature, and
|
// Clearly this is not sufficient for a general purpose feature, and
|
||||||
// we'd want to read from the library's metadata to determine which
|
// we'd want to read from the library's metadata to determine which
|
||||||
// object files come from where and selectively skip them.
|
// object files come from where and selectively skip them.
|
||||||
let skip_object_files = native_libs.iter().any(|lib| {
|
let skip_object_files = native_libs.iter().any(|lib| {
|
||||||
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
|
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
|
||||||
&& !relevant_lib(sess, lib)
|
&& !relevant_lib(sess, lib)
|
||||||
});
|
});
|
||||||
|
|
||||||
let lto = are_upstream_rust_objects_already_included(sess)
|
let lto = are_upstream_rust_objects_already_included(sess)
|
||||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||||
|
|
||||||
// Ignoring obj file starting with the crate name
|
// Ignoring obj file starting with the crate name
|
||||||
// as simple comparison is not enough - there
|
// as simple comparison is not enough - there
|
||||||
// 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(
|
ab.add_archive(
|
||||||
path,
|
path,
|
||||||
Box::new(move |fname: &str| {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't include Rust objects if LTO is enabled
|
// Don't include Rust objects if LTO is enabled
|
||||||
if lto && looks_like_rust_object_file(fname) {
|
if lto && looks_like_rust_object_file(fname) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if this is *not* a rust object and we're skipping
|
// Otherwise if this is *not* a rust object and we're skipping
|
||||||
// objects then skip this file
|
// objects then skip this file
|
||||||
if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
|
if skip_object_files
|
||||||
return true;
|
&& (!fname.starts_with(&obj_start) || !fname.ends_with(".o"))
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 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());
|
||||||
|
},
|
||||||
|
);
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
sess.emit_fatal(e);
|
sess.emit_fatal(e);
|
||||||
}
|
}
|
||||||
@ -1354,7 +1357,8 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
|
|||||||
if !lib_args.is_empty() {
|
if !lib_args.is_empty() {
|
||||||
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
||||||
// Prefix for greppability
|
// Prefix for greppability
|
||||||
sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") });
|
// Note: This must not be translated as tools are allowed to depend on this exact string.
|
||||||
|
sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +1002,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
|
|
||||||
let mut each_linked_rlib_for_lto = Vec::new();
|
let mut each_linked_rlib_for_lto = Vec::new();
|
||||||
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -444,12 +444,6 @@ pub struct UnableToRun<'a> {
|
|||||||
#[diag(codegen_ssa_static_library_native_artifacts)]
|
#[diag(codegen_ssa_static_library_native_artifacts)]
|
||||||
pub struct StaticLibraryNativeArtifacts;
|
pub struct StaticLibraryNativeArtifacts;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(codegen_ssa_native_static_libs)]
|
|
||||||
pub struct NativeStaticLibs {
|
|
||||||
pub arguments: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(codegen_ssa_link_script_unavailable)]
|
#[diag(codegen_ssa_link_script_unavailable)]
|
||||||
pub struct LinkScriptUnavailable;
|
pub struct LinkScriptUnavailable;
|
||||||
|
@ -157,8 +157,6 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
|
|||||||
|
|
||||||
codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
|
codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
|
||||||
|
|
||||||
codegen_ssa_native_static_libs = native-static-libs: {$arguments}
|
|
||||||
|
|
||||||
codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
|
codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
|
||||||
|
|
||||||
codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
|
codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
|
||||||
|
Loading…
Reference in New Issue
Block a user