Skip to content

Commit fe7aab1

Browse files
committed
linker: Move some inner functions to the outside
Inline `fn unlib`
1 parent e792de2 commit fe7aab1

File tree

1 file changed

+127
-133
lines changed
  • compiler/rustc_codegen_ssa/src/back

1 file changed

+127
-133
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 127 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_span::symbol::Symbol;
2424
use rustc_span::DebuggerVisualizerFile;
2525
use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
2626
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
27-
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, Target};
27+
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
2828

2929
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
3030
use super::command::Command;
@@ -2512,138 +2512,6 @@ fn add_upstream_rust_crates<'a>(
25122512
link_dynamic,
25132513
);
25142514
}
2515-
2516-
// Converts a library file-stem into a cc -l argument
2517-
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
2518-
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
2519-
}
2520-
2521-
// Adds the static "rlib" versions of all crates to the command line.
2522-
// There's a bit of magic which happens here specifically related to LTO,
2523-
// namely that we remove upstream object files.
2524-
//
2525-
// When performing LTO, almost(*) all of the bytecode from the upstream
2526-
// libraries has already been included in our object file output. As a
2527-
// result we need to remove the object files in the upstream libraries so
2528-
// the linker doesn't try to include them twice (or whine about duplicate
2529-
// symbols). We must continue to include the rest of the rlib, however, as
2530-
// it may contain static native libraries which must be linked in.
2531-
//
2532-
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2533-
// their bytecode wasn't included. The object files in those libraries must
2534-
// still be passed to the linker.
2535-
//
2536-
// Note, however, that if we're not doing LTO we can just pass the rlib
2537-
// blindly to the linker (fast) because it's fine if it's not actually
2538-
// included as we're at the end of the dependency chain.
2539-
fn add_static_crate<'a>(
2540-
cmd: &mut dyn Linker,
2541-
sess: &'a Session,
2542-
archive_builder_builder: &dyn ArchiveBuilderBuilder,
2543-
codegen_results: &CodegenResults,
2544-
tmpdir: &Path,
2545-
cnum: CrateNum,
2546-
bundled_lib_file_names: &FxHashSet<Symbol>,
2547-
) {
2548-
let src = &codegen_results.crate_info.used_crate_source[&cnum];
2549-
let cratepath = &src.rlib.as_ref().unwrap().0;
2550-
2551-
let mut link_upstream = |path: &Path| {
2552-
cmd.link_rlib(&fix_windows_verbatim_for_gcc(path));
2553-
};
2554-
2555-
// See the comment above in `link_staticlib` and `link_rlib` for why if
2556-
// there's a static library that's not relevant we skip all object
2557-
// files.
2558-
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
2559-
let skip_native = native_libs.iter().any(|lib| {
2560-
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
2561-
&& !relevant_lib(sess, lib)
2562-
});
2563-
2564-
if (!are_upstream_rust_objects_already_included(sess)
2565-
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum))
2566-
&& !skip_native
2567-
{
2568-
link_upstream(cratepath);
2569-
return;
2570-
}
2571-
2572-
let dst = tmpdir.join(cratepath.file_name().unwrap());
2573-
let name = cratepath.file_name().unwrap().to_str().unwrap();
2574-
let name = &name[3..name.len() - 5]; // chop off lib/.rlib
2575-
let bundled_lib_file_names = bundled_lib_file_names.clone();
2576-
2577-
sess.prof.generic_activity_with_arg("link_altering_rlib", name).run(|| {
2578-
let canonical_name = name.replace('-', "_");
2579-
let upstream_rust_objects_already_included =
2580-
are_upstream_rust_objects_already_included(sess);
2581-
let is_builtins = sess.target.no_builtins
2582-
|| !codegen_results.crate_info.is_no_builtins.contains(&cnum);
2583-
2584-
let mut archive = archive_builder_builder.new_archive_builder(sess);
2585-
if let Err(error) = archive.add_archive(
2586-
cratepath,
2587-
Box::new(move |f| {
2588-
if f == METADATA_FILENAME {
2589-
return true;
2590-
}
2591-
2592-
let canonical = f.replace('-', "_");
2593-
2594-
let is_rust_object =
2595-
canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);
2596-
2597-
// If we've been requested to skip all native object files
2598-
// (those not generated by the rust compiler) then we can skip
2599-
// this file. See above for why we may want to do this.
2600-
let skip_because_cfg_say_so = skip_native && !is_rust_object;
2601-
2602-
// If we're performing LTO and this is a rust-generated object
2603-
// file, then we don't need the object file as it's part of the
2604-
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
2605-
// though, so we let that object file slide.
2606-
let skip_because_lto =
2607-
upstream_rust_objects_already_included && is_rust_object && is_builtins;
2608-
2609-
// We skip native libraries because:
2610-
// 1. This native libraries won't be used from the generated rlib,
2611-
// so we can throw them away to avoid the copying work.
2612-
// 2. We can't allow it to be a single remaining entry in archive
2613-
// as some linkers may complain on that.
2614-
if bundled_lib_file_names.contains(&Symbol::intern(f)) {
2615-
return true;
2616-
}
2617-
2618-
if skip_because_cfg_say_so || skip_because_lto {
2619-
return true;
2620-
}
2621-
2622-
false
2623-
}),
2624-
) {
2625-
sess.emit_fatal(errors::RlibArchiveBuildFailure { error });
2626-
}
2627-
if archive.build(&dst) {
2628-
link_upstream(&dst);
2629-
}
2630-
});
2631-
}
2632-
2633-
// Same thing as above, but for dynamic crates instead of static crates.
2634-
fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
2635-
// Just need to tell the linker about where the library lives and
2636-
// what its name is
2637-
let parent = cratepath.parent();
2638-
if let Some(dir) = parent {
2639-
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
2640-
}
2641-
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
2642-
cmd.link_rust_dylib(
2643-
&unlib(&sess.target, filestem),
2644-
parent.unwrap_or_else(|| Path::new("")),
2645-
);
2646-
}
26472515
}
26482516

26492517
fn add_upstream_native_libraries(
@@ -2684,6 +2552,132 @@ fn add_upstream_native_libraries(
26842552
}
26852553
}
26862554

2555+
// Adds the static "rlib" versions of all crates to the command line.
2556+
// There's a bit of magic which happens here specifically related to LTO,
2557+
// namely that we remove upstream object files.
2558+
//
2559+
// When performing LTO, almost(*) all of the bytecode from the upstream
2560+
// libraries has already been included in our object file output. As a
2561+
// result we need to remove the object files in the upstream libraries so
2562+
// the linker doesn't try to include them twice (or whine about duplicate
2563+
// symbols). We must continue to include the rest of the rlib, however, as
2564+
// it may contain static native libraries which must be linked in.
2565+
//
2566+
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2567+
// their bytecode wasn't included. The object files in those libraries must
2568+
// still be passed to the linker.
2569+
//
2570+
// Note, however, that if we're not doing LTO we can just pass the rlib
2571+
// blindly to the linker (fast) because it's fine if it's not actually
2572+
// included as we're at the end of the dependency chain.
2573+
fn add_static_crate<'a>(
2574+
cmd: &mut dyn Linker,
2575+
sess: &'a Session,
2576+
archive_builder_builder: &dyn ArchiveBuilderBuilder,
2577+
codegen_results: &CodegenResults,
2578+
tmpdir: &Path,
2579+
cnum: CrateNum,
2580+
bundled_lib_file_names: &FxHashSet<Symbol>,
2581+
) {
2582+
let src = &codegen_results.crate_info.used_crate_source[&cnum];
2583+
let cratepath = &src.rlib.as_ref().unwrap().0;
2584+
2585+
let mut link_upstream = |path: &Path| {
2586+
cmd.link_rlib(&fix_windows_verbatim_for_gcc(path));
2587+
};
2588+
2589+
// See the comment above in `link_staticlib` and `link_rlib` for why if
2590+
// there's a static library that's not relevant we skip all object
2591+
// files.
2592+
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
2593+
let skip_native = native_libs.iter().any(|lib| {
2594+
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
2595+
&& !relevant_lib(sess, lib)
2596+
});
2597+
2598+
if (!are_upstream_rust_objects_already_included(sess)
2599+
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum))
2600+
&& !skip_native
2601+
{
2602+
link_upstream(cratepath);
2603+
return;
2604+
}
2605+
2606+
let dst = tmpdir.join(cratepath.file_name().unwrap());
2607+
let name = cratepath.file_name().unwrap().to_str().unwrap();
2608+
let name = &name[3..name.len() - 5]; // chop off lib/.rlib
2609+
let bundled_lib_file_names = bundled_lib_file_names.clone();
2610+
2611+
sess.prof.generic_activity_with_arg("link_altering_rlib", name).run(|| {
2612+
let canonical_name = name.replace('-', "_");
2613+
let upstream_rust_objects_already_included =
2614+
are_upstream_rust_objects_already_included(sess);
2615+
let is_builtins =
2616+
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
2617+
2618+
let mut archive = archive_builder_builder.new_archive_builder(sess);
2619+
if let Err(e) = archive.add_archive(
2620+
cratepath,
2621+
Box::new(move |f| {
2622+
if f == METADATA_FILENAME {
2623+
return true;
2624+
}
2625+
2626+
let canonical = f.replace('-', "_");
2627+
2628+
let is_rust_object =
2629+
canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);
2630+
2631+
// If we've been requested to skip all native object files
2632+
// (those not generated by the rust compiler) then we can skip
2633+
// this file. See above for why we may want to do this.
2634+
let skip_because_cfg_say_so = skip_native && !is_rust_object;
2635+
2636+
// If we're performing LTO and this is a rust-generated object
2637+
// file, then we don't need the object file as it's part of the
2638+
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
2639+
// though, so we let that object file slide.
2640+
let skip_because_lto =
2641+
upstream_rust_objects_already_included && is_rust_object && is_builtins;
2642+
2643+
// We skip native libraries because:
2644+
// 1. This native libraries won't be used from the generated rlib,
2645+
// so we can throw them away to avoid the copying work.
2646+
// 2. We can't allow it to be a single remaining entry in archive
2647+
// as some linkers may complain on that.
2648+
if bundled_lib_file_names.contains(&Symbol::intern(f)) {
2649+
return true;
2650+
}
2651+
2652+
if skip_because_cfg_say_so || skip_because_lto {
2653+
return true;
2654+
}
2655+
2656+
false
2657+
}),
2658+
) {
2659+
sess.fatal(&format!("failed to build archive from rlib: {}", e));
2660+
}
2661+
if archive.build(&dst) {
2662+
link_upstream(&dst);
2663+
}
2664+
});
2665+
}
2666+
2667+
// Same thing as above, but for dynamic crates instead of static crates.
2668+
fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
2669+
// Just need to tell the linker about where the library lives and
2670+
// what its name is
2671+
let parent = cratepath.parent();
2672+
if let Some(dir) = parent {
2673+
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
2674+
}
2675+
let stem = cratepath.file_stem().unwrap().to_str().unwrap();
2676+
// Convert library file-stem into a cc -l argument.
2677+
let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 };
2678+
cmd.link_rust_dylib(&stem[prefix..], parent.unwrap_or_else(|| Path::new("")));
2679+
}
2680+
26872681
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
26882682
match lib.cfg {
26892683
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),

0 commit comments

Comments
 (0)