linker: Simplify linking of compiler_builtins and profiler_builtins

This also fixes linking of native libraries bundled into these crates when `-Zpacked-bundled-libs` is enabled
This commit is contained in:
Vadim Petrochenkov 2022-10-20 18:57:47 +04:00
parent cae3c936eb
commit e792de28c8
2 changed files with 46 additions and 74 deletions

View File

@ -2425,10 +2425,6 @@ fn add_local_native_libraries(
); );
} }
/// # Linking Rust crates and their non-bundled static 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>( fn add_upstream_rust_crates<'a>(
cmd: &mut dyn Linker, cmd: &mut dyn Linker,
sess: &'a Session, sess: &'a Session,
@ -2444,7 +2440,6 @@ fn add_upstream_rust_crates<'a>(
// Linking to a rlib involves just passing it to the linker (the linker // Linking to a rlib involves just passing it to the linker (the linker
// will slurp up the object files inside), and linking to a dynamic library // will slurp up the object files inside), and linking to a dynamic library
// involves just passing the right -l flag. // involves just passing the right -l flag.
let (_, data) = codegen_results let (_, data) = codegen_results
.crate_info .crate_info
.dependency_formats .dependency_formats
@ -2452,59 +2447,45 @@ fn add_upstream_rust_crates<'a>(
.find(|(ty, _)| *ty == crate_type) .find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list"); .expect("failed to find crate type in dependency format list");
// Invoke get_used_crates to ensure that we get a topological sorting of
// crates.
let deps = &codegen_results.crate_info.used_crates;
let mut compiler_builtins = None;
let search_paths = OnceCell::new(); let search_paths = OnceCell::new();
for &cnum in &codegen_results.crate_info.used_crates {
for &cnum in deps.iter() { // We may not pass all crates through to the linker. Some crates may appear statically in
// We may not pass all crates through to the linker. Some crates may // an existing dylib, meaning we'll pick up all the symbols from the dylib.
// appear statically in an existing dylib, meaning we'll pick up all the // We must always link crates `compiler_builtins` and `profiler_builtins` statically.
// symbols from the dylib. // Even if they were already included into a dylib
// (e.g. `libstd` when `-C prefer-dynamic` is used).
let linkage = data[cnum.as_usize() - 1]; let linkage = data[cnum.as_usize() - 1];
let bundled_libs = let link_static_crate = linkage == Linkage::Static
if sess.opts.unstable_opts.packed_bundled_libs && linkage == Linkage::Static { || linkage == Linkage::IncludedFromDylib
codegen_results.crate_info.native_libraries[&cnum] && (codegen_results.crate_info.compiler_builtins == Some(cnum)
.iter() || codegen_results.crate_info.profiler_runtime == Some(cnum));
.filter_map(|lib| lib.filename)
.collect::<FxHashSet<_>>() let mut bundled_libs = Default::default();
} else {
Default::default()
};
match linkage { match linkage {
_ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { Linkage::Static | Linkage::IncludedFromDylib => {
add_static_crate( if link_static_crate {
cmd, if sess.opts.unstable_opts.packed_bundled_libs {
sess, bundled_libs = codegen_results.crate_info.native_libraries[&cnum]
archive_builder_builder, .iter()
codegen_results, .filter_map(|lib| lib.filename)
tmpdir, .collect();
cnum, }
&Default::default(), add_static_crate(
); cmd,
sess,
archive_builder_builder,
codegen_results,
tmpdir,
cnum,
&bundled_libs,
);
}
} }
// compiler-builtins are always placed last to ensure that they're
// linked correctly.
_ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
assert!(compiler_builtins.is_none());
compiler_builtins = Some(cnum);
}
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Linkage::Static => add_static_crate(
cmd,
sess,
archive_builder_builder,
codegen_results,
tmpdir,
cnum,
&bundled_libs,
),
Linkage::Dynamic => { Linkage::Dynamic => {
let src = &codegen_results.crate_info.used_crate_source[&cnum]; let src = &codegen_results.crate_info.used_crate_source[&cnum];
add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0); add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0);
} }
Linkage::NotLinked => {}
} }
// Static libraries are linked for a subset of linked upstream crates. // Static libraries are linked for a subset of linked upstream crates.
@ -2514,7 +2495,8 @@ fn add_upstream_rust_crates<'a>(
// the native library because it is already linked into the dylib, and even if // the native library because it is already linked into the dylib, and even if
// inline/const/generic functions from the dylib can refer to symbols from the native // inline/const/generic functions from the dylib can refer to symbols from the native
// library, those symbols should be exported and available from the dylib anyway. // library, those symbols should be exported and available from the dylib anyway.
let link_static = linkage == Linkage::Static; // 3. Libraries bundled into `(compiler,profiler)_builtins` are special, see above.
let link_static = link_static_crate;
// Dynamic libraries are not linked here, see the FIXME in `add_upstream_native_libraries`. // Dynamic libraries are not linked here, see the FIXME in `add_upstream_native_libraries`.
let link_dynamic = false; let link_dynamic = false;
add_native_libs_from_crate( add_native_libs_from_crate(
@ -2531,23 +2513,6 @@ fn add_upstream_rust_crates<'a>(
); );
} }
// compiler-builtins are always placed last to ensure that they're
// linked correctly.
// We must always link the `compiler_builtins` crate statically. Even if it
// was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
// is used)
if let Some(cnum) = compiler_builtins {
add_static_crate(
cmd,
sess,
archive_builder_builder,
codegen_results,
tmpdir,
cnum,
&Default::default(),
);
}
// Converts a library file-stem into a cc -l argument // Converts a library file-stem into a cc -l argument
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str { fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem } if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }

View File

@ -833,20 +833,30 @@ impl CrateInfo {
// //
// In order to get this left-to-right dependency ordering, we use the reverse // In order to get this left-to-right dependency ordering, we use the reverse
// postorder of all crates putting the leaves at the right-most positions. // postorder of all crates putting the leaves at the right-most positions.
let used_crates = tcx let mut compiler_builtins = None;
let mut used_crates: Vec<_> = tcx
.postorder_cnums(()) .postorder_cnums(())
.iter() .iter()
.rev() .rev()
.copied() .copied()
.filter(|&cnum| !tcx.dep_kind(cnum).macros_only()) .filter(|&cnum| {
let link = !tcx.dep_kind(cnum).macros_only();
if link && tcx.is_compiler_builtins(cnum) {
compiler_builtins = Some(cnum);
return false;
}
link
})
.collect(); .collect();
// `compiler_builtins` are always placed last to ensure that they're linked correctly.
used_crates.extend(compiler_builtins);
let mut info = CrateInfo { let mut info = CrateInfo {
target_cpu, target_cpu,
exported_symbols, exported_symbols,
linked_symbols, linked_symbols,
local_crate_name, local_crate_name,
compiler_builtins: None, compiler_builtins,
profiler_runtime: None, profiler_runtime: None,
is_no_builtins: Default::default(), is_no_builtins: Default::default(),
native_libraries: Default::default(), native_libraries: Default::default(),
@ -872,9 +882,6 @@ impl CrateInfo {
let used_crate_source = tcx.used_crate_source(cnum); let used_crate_source = tcx.used_crate_source(cnum);
info.used_crate_source.insert(cnum, used_crate_source.clone()); info.used_crate_source.insert(cnum, used_crate_source.clone());
if tcx.is_compiler_builtins(cnum) {
info.compiler_builtins = Some(cnum);
}
if tcx.is_profiler_runtime(cnum) { if tcx.is_profiler_runtime(cnum) {
info.profiler_runtime = Some(cnum); info.profiler_runtime = Some(cnum);
} }