linker: Move some inner functions to the outside
Inline `fn unlib`
This commit is contained in:
parent
e792de28c8
commit
fe7aab13b1
1 changed files with 127 additions and 133 deletions
|
@ -24,7 +24,7 @@ use rustc_span::symbol::Symbol;
|
|||
use rustc_span::DebuggerVisualizerFile;
|
||||
use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
|
||||
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
|
||||
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, Target};
|
||||
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
|
||||
|
||||
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
||||
use super::command::Command;
|
||||
|
@ -2512,31 +2512,65 @@ fn add_upstream_rust_crates<'a>(
|
|||
link_dynamic,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a library file-stem into a cc -l argument
|
||||
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
|
||||
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
|
||||
fn add_upstream_native_libraries(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &Session,
|
||||
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||
codegen_results: &CodegenResults,
|
||||
tmpdir: &Path,
|
||||
) {
|
||||
let search_path = OnceCell::new();
|
||||
for &cnum in &codegen_results.crate_info.used_crates {
|
||||
// Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
|
||||
// FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
|
||||
// are linked together with their respective upstream crates, and in their originally
|
||||
// specified order. This is slightly breaking due to our use of `--as-needed` (see crater
|
||||
// results in https://github.com/rust-lang/rust/pull/102832#issuecomment-1279772306).
|
||||
let link_static = false;
|
||||
// Dynamic libraries are linked for all linked upstream crates.
|
||||
// 1. If the upstream crate is a directly linked rlib then we must link the native library
|
||||
// because the rlib is just an archive.
|
||||
// 2. If the upstream crate is a dylib or a rlib linked through dylib, then we have to link
|
||||
// the native library too because inline/const/generic functions from the dylib can refer
|
||||
// to symbols from the native library, so the native library providing those symbols should
|
||||
// be available when linking our final binary.
|
||||
let link_dynamic = true;
|
||||
add_native_libs_from_crate(
|
||||
cmd,
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results,
|
||||
tmpdir,
|
||||
&search_path,
|
||||
&Default::default(),
|
||||
cnum,
|
||||
link_static,
|
||||
link_dynamic,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the static "rlib" versions of all crates to the command line.
|
||||
// There's a bit of magic which happens here specifically related to LTO,
|
||||
// namely that we remove upstream object files.
|
||||
//
|
||||
// When performing LTO, almost(*) all of the bytecode from the upstream
|
||||
// libraries has already been included in our object file output. As a
|
||||
// result we need to remove the object files in the upstream libraries so
|
||||
// the linker doesn't try to include them twice (or whine about duplicate
|
||||
// symbols). We must continue to include the rest of the rlib, however, as
|
||||
// it may contain static native libraries which must be linked in.
|
||||
//
|
||||
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
|
||||
// their bytecode wasn't included. The object files in those libraries must
|
||||
// still be passed to the linker.
|
||||
//
|
||||
// Note, however, that if we're not doing LTO we can just pass the rlib
|
||||
// blindly to the linker (fast) because it's fine if it's not actually
|
||||
// included as we're at the end of the dependency chain.
|
||||
fn add_static_crate<'a>(
|
||||
// Adds the static "rlib" versions of all crates to the command line.
|
||||
// There's a bit of magic which happens here specifically related to LTO,
|
||||
// namely that we remove upstream object files.
|
||||
//
|
||||
// When performing LTO, almost(*) all of the bytecode from the upstream
|
||||
// libraries has already been included in our object file output. As a
|
||||
// result we need to remove the object files in the upstream libraries so
|
||||
// the linker doesn't try to include them twice (or whine about duplicate
|
||||
// symbols). We must continue to include the rest of the rlib, however, as
|
||||
// it may contain static native libraries which must be linked in.
|
||||
//
|
||||
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
|
||||
// their bytecode wasn't included. The object files in those libraries must
|
||||
// still be passed to the linker.
|
||||
//
|
||||
// Note, however, that if we're not doing LTO we can just pass the rlib
|
||||
// blindly to the linker (fast) because it's fine if it's not actually
|
||||
// included as we're at the end of the dependency chain.
|
||||
fn add_static_crate<'a>(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &'a Session,
|
||||
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||
|
@ -2544,7 +2578,7 @@ fn add_upstream_rust_crates<'a>(
|
|||
tmpdir: &Path,
|
||||
cnum: CrateNum,
|
||||
bundled_lib_file_names: &FxHashSet<Symbol>,
|
||||
) {
|
||||
) {
|
||||
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||
|
||||
|
@ -2578,11 +2612,11 @@ fn add_upstream_rust_crates<'a>(
|
|||
let canonical_name = name.replace('-', "_");
|
||||
let upstream_rust_objects_already_included =
|
||||
are_upstream_rust_objects_already_included(sess);
|
||||
let is_builtins = sess.target.no_builtins
|
||||
|| !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
let is_builtins =
|
||||
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
|
||||
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||
if let Err(error) = archive.add_archive(
|
||||
if let Err(e) = archive.add_archive(
|
||||
cratepath,
|
||||
Box::new(move |f| {
|
||||
if f == METADATA_FILENAME {
|
||||
|
@ -2622,66 +2656,26 @@ fn add_upstream_rust_crates<'a>(
|
|||
false
|
||||
}),
|
||||
) {
|
||||
sess.emit_fatal(errors::RlibArchiveBuildFailure { error });
|
||||
sess.fatal(&format!("failed to build archive from rlib: {}", e));
|
||||
}
|
||||
if archive.build(&dst) {
|
||||
link_upstream(&dst);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Same thing as above, but for dynamic crates instead of static crates.
|
||||
fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
||||
// Same thing as above, but for dynamic crates instead of static crates.
|
||||
fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
||||
// Just need to tell the linker about where the library lives and
|
||||
// what its name is
|
||||
let parent = cratepath.parent();
|
||||
if let Some(dir) = parent {
|
||||
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
|
||||
}
|
||||
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
|
||||
cmd.link_rust_dylib(
|
||||
&unlib(&sess.target, filestem),
|
||||
parent.unwrap_or_else(|| Path::new("")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_upstream_native_libraries(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &Session,
|
||||
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||
codegen_results: &CodegenResults,
|
||||
tmpdir: &Path,
|
||||
) {
|
||||
let search_path = OnceCell::new();
|
||||
for &cnum in &codegen_results.crate_info.used_crates {
|
||||
// Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
|
||||
// FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
|
||||
// are linked together with their respective upstream crates, and in their originally
|
||||
// specified order. This is slightly breaking due to our use of `--as-needed` (see crater
|
||||
// results in https://github.com/rust-lang/rust/pull/102832#issuecomment-1279772306).
|
||||
let link_static = false;
|
||||
// Dynamic libraries are linked for all linked upstream crates.
|
||||
// 1. If the upstream crate is a directly linked rlib then we must link the native library
|
||||
// because the rlib is just an archive.
|
||||
// 2. If the upstream crate is a dylib or a rlib linked through dylib, then we have to link
|
||||
// the native library too because inline/const/generic functions from the dylib can refer
|
||||
// to symbols from the native library, so the native library providing those symbols should
|
||||
// be available when linking our final binary.
|
||||
let link_dynamic = true;
|
||||
add_native_libs_from_crate(
|
||||
cmd,
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results,
|
||||
tmpdir,
|
||||
&search_path,
|
||||
&Default::default(),
|
||||
cnum,
|
||||
link_static,
|
||||
link_dynamic,
|
||||
);
|
||||
}
|
||||
let stem = cratepath.file_stem().unwrap().to_str().unwrap();
|
||||
// Convert library file-stem into a cc -l argument.
|
||||
let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 };
|
||||
cmd.link_rust_dylib(&stem[prefix..], parent.unwrap_or_else(|| Path::new("")));
|
||||
}
|
||||
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue