Skip to content

Commit d9e317a

Browse files
committed
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`.
2 parents 659e169 + 7705116 commit d9e317a

File tree

4 files changed

+81
-85
lines changed

4 files changed

+81
-85
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+80-76
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
1111
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
1212
use rustc_middle::middle::dependency_format::Linkage;
1313
use rustc_middle::middle::exported_symbols::SymbolExportKind;
14-
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
14+
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
1515
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
1616
use rustc_session::cstore::DllImport;
1717
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -208,16 +208,16 @@ pub fn link_binary<'a>(
208208
Ok(())
209209
}
210210

211+
// Crate type is not passed when calculating the dylibs to include for LTO. In that case all
212+
// crate types must use the same dependency formats.
211213
pub fn each_linked_rlib(
212-
sess: &Session,
213214
info: &CrateInfo,
215+
crate_type: Option<CrateType>,
214216
f: &mut dyn FnMut(CrateNum, &Path),
215217
) -> Result<(), errors::LinkRlibError> {
216218
let crates = info.used_crates.iter();
217-
let mut fmts = None;
218219

219-
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
220-
if lto_active {
220+
let fmts = if crate_type.is_none() {
221221
for combination in info.dependency_formats.iter().combinations(2) {
222222
let (ty1, list1) = &combination[0];
223223
let (ty2, list2) = &combination[1];
@@ -230,27 +230,23 @@ pub fn each_linked_rlib(
230230
});
231231
}
232232
}
233-
}
234-
235-
for (ty, list) in info.dependency_formats.iter() {
236-
match ty {
237-
CrateType::Executable
238-
| CrateType::Staticlib
239-
| CrateType::Cdylib
240-
| CrateType::ProcMacro => {
241-
fmts = Some(list);
242-
break;
243-
}
244-
CrateType::Dylib if lto_active => {
245-
fmts = Some(list);
246-
break;
247-
}
248-
_ => {}
233+
if info.dependency_formats.is_empty() {
234+
return Err(errors::LinkRlibError::MissingFormat);
249235
}
250-
}
251-
let Some(fmts) = fmts else {
252-
return Err(errors::LinkRlibError::MissingFormat);
236+
&info.dependency_formats[0].1
237+
} else {
238+
let fmts = info
239+
.dependency_formats
240+
.iter()
241+
.find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None });
242+
243+
let Some(fmts) = fmts else {
244+
return Err(errors::LinkRlibError::MissingFormat);
245+
};
246+
247+
fmts
253248
};
249+
254250
for &cnum in crates {
255251
match fmts.get(cnum.as_usize() - 1) {
256252
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
@@ -516,64 +512,71 @@ fn link_staticlib<'a>(
516512
)?;
517513
let mut all_native_libs = vec![];
518514

519-
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
520-
let name = codegen_results.crate_info.crate_name[&cnum];
521-
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
522-
523-
// Here when we include the rlib into our staticlib we need to make a
524-
// decision whether to include the extra object files along the way.
525-
// These extra object files come from statically included native
526-
// libraries, but they may be cfg'd away with #[link(cfg(..))].
527-
//
528-
// This unstable feature, though, only needs liblibc to work. The only
529-
// use case there is where musl is statically included in liblibc.rlib,
530-
// so if we don't want the included version we just need to skip it. As
531-
// a result the logic here is that if *any* linked library is cfg'd away
532-
// we just skip all object files.
533-
//
534-
// Clearly this is not sufficient for a general purpose feature, and
535-
// we'd want to read from the library's metadata to determine which
536-
// object files come from where and selectively skip them.
537-
let skip_object_files = native_libs.iter().any(|lib| {
538-
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
539-
&& !relevant_lib(sess, lib)
540-
});
515+
let res = each_linked_rlib(
516+
&codegen_results.crate_info,
517+
Some(CrateType::Staticlib),
518+
&mut |cnum, path| {
519+
let name = codegen_results.crate_info.crate_name[&cnum];
520+
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
521+
522+
// Here when we include the rlib into our staticlib we need to make a
523+
// decision whether to include the extra object files along the way.
524+
// These extra object files come from statically included native
525+
// libraries, but they may be cfg'd away with #[link(cfg(..))].
526+
//
527+
// This unstable feature, though, only needs liblibc to work. The only
528+
// use case there is where musl is statically included in liblibc.rlib,
529+
// so if we don't want the included version we just need to skip it. As
530+
// a result the logic here is that if *any* linked library is cfg'd away
531+
// we just skip all object files.
532+
//
533+
// Clearly this is not sufficient for a general purpose feature, and
534+
// we'd want to read from the library's metadata to determine which
535+
// object files come from where and selectively skip them.
536+
let skip_object_files = native_libs.iter().any(|lib| {
537+
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
538+
&& !relevant_lib(sess, lib)
539+
});
541540

542-
let lto = are_upstream_rust_objects_already_included(sess)
543-
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
541+
let lto = are_upstream_rust_objects_already_included(sess)
542+
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
544543

545-
// Ignoring obj file starting with the crate name
546-
// as simple comparison is not enough - there
547-
// might be also an extra name suffix
548-
let obj_start = name.as_str().to_owned();
544+
// Ignoring obj file starting with the crate name
545+
// as simple comparison is not enough - there
546+
// might be also an extra name suffix
547+
let obj_start = name.as_str().to_owned();
549548

550-
ab.add_archive(
551-
path,
552-
Box::new(move |fname: &str| {
553-
// Ignore metadata files, no matter the name.
554-
if fname == METADATA_FILENAME {
555-
return true;
556-
}
549+
ab.add_archive(
550+
path,
551+
Box::new(move |fname: &str| {
552+
// Ignore metadata files, no matter the name.
553+
if fname == METADATA_FILENAME {
554+
return true;
555+
}
557556

558-
// Don't include Rust objects if LTO is enabled
559-
if lto && looks_like_rust_object_file(fname) {
560-
return true;
561-
}
557+
// Don't include Rust objects if LTO is enabled
558+
if lto && looks_like_rust_object_file(fname) {
559+
return true;
560+
}
562561

563-
// Otherwise if this is *not* a rust object and we're skipping
564-
// objects then skip this file
565-
if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
566-
return true;
567-
}
562+
// Otherwise if this is *not* a rust object and we're skipping
563+
// objects then skip this file
564+
if skip_object_files
565+
&& (!fname.starts_with(&obj_start) || !fname.ends_with(".o"))
566+
{
567+
return true;
568+
}
568569

569-
// ok, don't skip this
570-
false
571-
}),
572-
)
573-
.unwrap();
570+
// ok, don't skip this
571+
false
572+
}),
573+
)
574+
.unwrap();
574575

575-
all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
576-
});
576+
all_native_libs
577+
.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
578+
},
579+
);
577580
if let Err(e) = res {
578581
sess.emit_fatal(e);
579582
}
@@ -1354,7 +1357,8 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
13541357
if !lib_args.is_empty() {
13551358
sess.emit_note(errors::StaticLibraryNativeArtifacts);
13561359
// Prefix for greppability
1357-
sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") });
1360+
// Note: This must not be translated as tools are allowed to depend on this exact string.
1361+
sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" ")));
13581362
}
13591363
}
13601364

compiler/rustc_codegen_ssa/src/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10021002
let sess = tcx.sess;
10031003

10041004
let mut each_linked_rlib_for_lto = Vec::new();
1005-
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
1005+
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
10061006
if link::ignored_for_lto(sess, crate_info, cnum) {
10071007
return;
10081008
}

compiler/rustc_codegen_ssa/src/errors.rs

-6
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,6 @@ pub struct LinkerFileStem;
444444
#[diag(codegen_ssa_static_library_native_artifacts)]
445445
pub struct StaticLibraryNativeArtifacts;
446446

447-
#[derive(Diagnostic)]
448-
#[diag(codegen_ssa_native_static_libs)]
449-
pub struct NativeStaticLibs {
450-
pub arguments: String,
451-
}
452-
453447
#[derive(Diagnostic)]
454448
#[diag(codegen_ssa_link_script_unavailable)]
455449
pub struct LinkScriptUnavailable;

compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,6 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
157157
158158
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.
159159
160-
codegen_ssa_native_static_libs = native-static-libs: {$arguments}
161-
162160
codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
163161
164162
codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}

0 commit comments

Comments
 (0)