Skip to content

linker: Refactor library linking methods in trait Linker #120099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
@@ -52,6 +52,15 @@ use std::path::{Path, PathBuf};
use std::process::{ExitStatus, Output, Stdio};
use std::{env, fmt, fs, io, mem, str};

#[derive(Default)]
pub struct SearchPaths(OnceCell<Vec<PathBuf>>);

impl SearchPaths {
pub(super) fn get(&self, sess: &Session) -> &[PathBuf] {
self.0.get_or_init(|| archive_search_paths(sess))
}
}

pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) {
if let Err(e) = fs::remove_file(path) {
if e.kind() != io::ErrorKind::NotFound {
@@ -1265,15 +1274,15 @@ fn link_sanitizer_runtime(
let path = find_sanitizer_runtime(sess, &filename);
let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
linker.link_dylib(&filename, false, true);
linker.link_dylib_by_name(&filename, false, true);
} else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" {
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
// compatible ASAN library.
linker.arg("/INFERASANLIBS");
} else {
let filename = format!("librustc{channel}_rt.{name}.a");
let path = find_sanitizer_runtime(sess, &filename).join(&filename);
linker.link_whole_rlib(&path);
linker.link_staticlib_by_path(&path, true);
}
}

@@ -2445,7 +2454,7 @@ fn add_native_libs_from_crate(
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults,
tmpdir: &Path,
search_paths: &OnceCell<Vec<PathBuf>>,
search_paths: &SearchPaths,
bundled_libs: &FxHashSet<Symbol>,
cnum: CrateNum,
link_static: bool,
@@ -2505,46 +2514,34 @@ fn add_native_libs_from_crate(
if let Some(filename) = lib.filename {
// If rlib contains native libs as archives, they are unpacked to tmpdir.
let path = tmpdir.join(filename.as_str());
if whole_archive {
cmd.link_whole_rlib(&path);
} else {
cmd.link_rlib(&path);
}
cmd.link_staticlib_by_path(&path, whole_archive);
}
} else {
if whole_archive {
cmd.link_whole_staticlib(
name,
verbatim,
search_paths.get_or_init(|| archive_search_paths(sess)),
);
} else {
cmd.link_staticlib(name, verbatim)
}
cmd.link_staticlib_by_name(name, verbatim, whole_archive, search_paths);
}
}
}
NativeLibKind::Dylib { as_needed } => {
if link_dynamic {
cmd.link_dylib(name, verbatim, as_needed.unwrap_or(true))
cmd.link_dylib_by_name(name, verbatim, as_needed.unwrap_or(true))
}
}
NativeLibKind::Unspecified => {
// If we are generating a static binary, prefer static library when the
// link kind is unspecified.
if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs {
if link_static {
cmd.link_staticlib(name, verbatim)
cmd.link_staticlib_by_name(name, verbatim, false, search_paths);
}
} else {
if link_dynamic {
cmd.link_dylib(name, verbatim, true);
cmd.link_dylib_by_name(name, verbatim, true);
}
}
}
NativeLibKind::Framework { as_needed } => {
if link_dynamic {
cmd.link_framework(name, as_needed.unwrap_or(true))
cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
}
}
NativeLibKind::RawDylib => {
@@ -2581,7 +2578,7 @@ fn add_local_native_libraries(
}
}

let search_paths = OnceCell::new();
let search_paths = SearchPaths::default();
// All static and dynamic native library dependencies are linked to the local crate.
let link_static = true;
let link_dynamic = true;
@@ -2623,7 +2620,7 @@ fn add_upstream_rust_crates<'a>(
.find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list");

let search_paths = OnceCell::new();
let search_paths = SearchPaths::default();
for &cnum in &codegen_results.crate_info.used_crates {
// We may not pass all crates through to the linker. Some crates may appear statically in
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
@@ -2698,7 +2695,7 @@ fn add_upstream_native_libraries(
tmpdir: &Path,
link_output_kind: LinkOutputKind,
) {
let search_path = OnceCell::new();
let search_paths = SearchPaths::default();
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
@@ -2720,7 +2717,7 @@ fn add_upstream_native_libraries(
archive_builder_builder,
codegen_results,
tmpdir,
&search_path,
&search_paths,
&Default::default(),
cnum,
link_static,
@@ -2791,7 +2788,7 @@ fn add_static_crate<'a>(
} else {
fix_windows_verbatim_for_gcc(path)
};
cmd.link_rlib(&rlib_path);
cmd.link_staticlib_by_path(&rlib_path, false);
};

if !are_upstream_rust_objects_already_included(sess)
@@ -2859,13 +2856,24 @@ 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();
// When producing a dll, the MSVC linker may not actually emit a
// `foo.lib` file if the dll doesn't actually export any symbols, so we
// check to see if the file is there and just omit linking to it if it's
// not present.
if sess.target.is_like_msvc && !cratepath.with_extension("dll.lib").exists() {
return;
}
if let Some(dir) = parent {
cmd.include_path(&rehome_sysroot_lib_dir(sess, dir));
}
let stem = cratepath.file_stem().unwrap().to_str().unwrap();
// "<dir>/name.dll -> name.dll" on windows-msvc
// "<dir>/name.dll -> name" on windows-gnu
// "<dir>/libname.<ext> -> name" elsewhere
let stem = if sess.target.is_like_msvc { cratepath.file_name() } else { cratepath.file_stem() };
let stem = 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("")));
cmd.link_dylib_by_name(&stem[prefix..], false, true);
}

fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
489 changes: 222 additions & 267 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::command::Command;
use super::symbol_export;
use crate::back::link::SearchPaths;
use crate::errors;
use rustc_span::symbol::sym;

@@ -166,13 +167,18 @@ pub fn get_linker<'a>(
pub trait Linker {
fn cmd(&mut self) -> &mut Command;
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path);
fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool);
fn link_rust_dylib(&mut self, lib: &str, path: &Path);
fn link_framework(&mut self, framework: &str, as_needed: bool);
fn link_staticlib(&mut self, lib: &str, verbatim: bool);
fn link_rlib(&mut self, lib: &Path);
fn link_whole_rlib(&mut self, lib: &Path);
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]);
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool);
fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
bug!("framework linked with unsupported linker")
}
fn link_staticlib_by_name(
&mut self,
name: &str,
verbatim: bool,
whole_archive: bool,
search_paths: &SearchPaths,
);
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool);
fn include_path(&mut self, path: &Path);
fn framework_path(&mut self, path: &Path);
fn output_filename(&mut self, path: &Path);
@@ -432,8 +438,8 @@ impl<'a> Linker for GccLinker<'a> {
}
}

fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool) {
if self.sess.target.os == "illumos" && lib == "c" {
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
if self.sess.target.os == "illumos" && name == "c" {
// libc will be added via late_link_args on illumos so that it will
// appear last in the library search order.
// FIXME: This should be replaced by a more complete and generic
@@ -454,7 +460,7 @@ impl<'a> Linker for GccLinker<'a> {
}
}
self.hint_dynamic();
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },));
if !as_needed {
if self.sess.target.is_like_osx {
// See above FIXME comment
@@ -463,14 +469,56 @@ impl<'a> Linker for GccLinker<'a> {
}
}
}
fn link_staticlib(&mut self, lib: &str, verbatim: bool) {

fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) {
self.hint_dynamic();
if !as_needed {
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
// flag but we have no way to detect that here.
// self.cmd.arg("-needed_framework").arg(name);
self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
}
self.cmd.arg("-framework").arg(name);
}

fn link_staticlib_by_name(
&mut self,
name: &str,
verbatim: bool,
whole_archive: bool,
search_paths: &SearchPaths,
) {
self.hint_static();
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
let colon = if verbatim && self.is_gnu { ":" } else { "" };
if !whole_archive {
self.cmd.arg(format!("-l{colon}{name}"));
} else if self.sess.target.is_like_osx {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
self.linker_arg("-force_load");
let search_paths = search_paths.get(self.sess);
self.linker_arg(find_native_static_library(name, verbatim, search_paths, self.sess));
} else {
self.linker_arg("--whole-archive");
self.cmd.arg(format!("-l{colon}{name}"));
self.linker_arg("--no-whole-archive");
}
}
fn link_rlib(&mut self, lib: &Path) {

fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
self.hint_static();
self.cmd.arg(lib);
if !whole_archive {
self.cmd.arg(path);
} else if self.sess.target.is_like_osx {
self.linker_arg("-force_load");
self.linker_arg(path);
} else {
self.linker_arg("--whole-archive");
self.linker_arg(path);
self.linker_arg("--no-whole-archive");
}
}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}
@@ -493,55 +541,6 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_args(&["-z", "norelro"]);
}

fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
self.hint_dynamic();
self.cmd.arg(format!("-l{lib}"));
}

fn link_framework(&mut self, framework: &str, as_needed: bool) {
self.hint_dynamic();
if !as_needed {
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
// flag but we have no way to detect that here.
// self.cmd.arg("-needed_framework").arg(framework);
self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
}
self.cmd.arg("-framework").arg(framework);
}

// Here we explicitly ask that the entire archive is included into the
// result artifact. For more details see #15460, but the gist is that
// the linker will strip away any unused objects in the archive if we
// don't otherwise explicitly reference them. This can occur for
// libraries which are just providing bindings, libraries with generic
// functions, etc.
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
self.hint_static();
let target = &self.sess.target;
if !target.is_like_osx {
self.linker_arg("--whole-archive");
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
self.linker_arg("--no-whole-archive");
} else {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
self.linker_arg("-force_load");
let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
self.linker_arg(&lib);
}
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
if self.sess.target.is_like_osx {
self.linker_arg("-force_load");
self.linker_arg(&lib);
} else {
self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
self.linker_arg("--no-whole-archive");
}
}

fn gc_sections(&mut self, keep_metadata: bool) {
// The dead_strip option to the linker specifies that functions and data
// unreachable by the entry point will be removed. This is quite useful
@@ -821,9 +820,32 @@ impl<'a> Linker for MsvcLinker<'a> {
}
}

fn link_rlib(&mut self, lib: &Path) {
self.cmd.arg(lib);
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" }));
}

fn link_staticlib_by_name(
&mut self,
name: &str,
verbatim: bool,
whole_archive: bool,
_search_paths: &SearchPaths,
) {
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
let suffix = if verbatim { "" } else { ".lib" };
self.cmd.arg(format!("{prefix}{name}{suffix}"));
}

fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
if !whole_archive {
self.cmd.arg(path);
} else {
let mut arg = OsString::from("/WHOLEARCHIVE:");
arg.push(path);
self.cmd.arg(arg);
}
}

fn add_object(&mut self, path: &Path) {
self.cmd.arg(path);
}
@@ -845,25 +867,6 @@ impl<'a> Linker for MsvcLinker<'a> {
self.cmd.arg("/OPT:NOREF,NOICF");
}

fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) {
self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" }));
}

fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
// When producing a dll, the MSVC linker may not actually emit a
// `foo.lib` file if the dll doesn't actually export any symbols, so we
// check to see if the file is there and just omit linking to it if it's
// not present.
let name = format!("{lib}.dll.lib");
if path.join(&name).exists() {
self.cmd.arg(name);
}
}

fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" }));
}

fn full_relro(&mut self) {
// noop
}
@@ -899,18 +902,7 @@ impl<'a> Linker for MsvcLinker<'a> {
fn framework_path(&mut self, _path: &Path) {
bug!("frameworks are not supported on windows")
}
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
bug!("frameworks are not supported on windows")
}

fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" }));
}
fn link_whole_rlib(&mut self, path: &Path) {
let mut arg = OsString::from("/WHOLEARCHIVE:");
arg.push(path);
self.cmd.arg(arg);
}
fn optimize(&mut self) {
// Needs more investigation of `/OPT` arguments
}
@@ -1057,43 +1049,35 @@ impl<'a> Linker for EmLinker<'a> {

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}

fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
self.cmd.arg("-l").arg(lib);
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
// Emscripten always links statically
self.cmd.arg("-l").arg(name);
}

fn output_filename(&mut self, path: &Path) {
self.cmd.arg("-o").arg(path);
fn link_staticlib_by_name(
&mut self,
name: &str,
_verbatim: bool,
_whole_archive: bool,
_search_paths: &SearchPaths,
) {
self.cmd.arg("-l").arg(name);
}

fn add_object(&mut self, path: &Path) {
fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
self.cmd.arg(path);
}

fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) {
// Emscripten always links statically
self.link_staticlib(lib, verbatim);
}

fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
// not supported?
self.link_staticlib(lib, verbatim);
}

fn link_whole_rlib(&mut self, lib: &Path) {
// not supported?
self.link_rlib(lib);
fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}

fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
self.link_dylib(lib, false, true);
fn output_filename(&mut self, path: &Path) {
self.cmd.arg("-o").arg(path);
}

fn link_rlib(&mut self, lib: &Path) {
self.add_object(lib);
fn add_object(&mut self, path: &Path) {
self.cmd.arg(path);
}

fn full_relro(&mut self) {
@@ -1112,10 +1096,6 @@ impl<'a> Linker for EmLinker<'a> {
bug!("frameworks are not supported on Emscripten")
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
bug!("frameworks are not supported on Emscripten")
}

fn gc_sections(&mut self, _keep_metadata: bool) {
// noop
}
@@ -1249,16 +1229,30 @@ impl<'a> Linker for WasmLd<'a> {
}
}

fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) {
self.cmd.arg("-l").arg(lib);
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
self.cmd.arg("-l").arg(name);
}

fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
self.cmd.arg("-l").arg(lib);
fn link_staticlib_by_name(
&mut self,
name: &str,
_verbatim: bool,
whole_archive: bool,
_search_paths: &SearchPaths,
) {
if !whole_archive {
self.cmd.arg("-l").arg(name);
} else {
self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive");
}
}

fn link_rlib(&mut self, lib: &Path) {
self.cmd.arg(lib);
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
if !whole_archive {
self.cmd.arg(path);
} else {
self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive");
}
}

fn include_path(&mut self, path: &Path) {
@@ -1283,22 +1277,6 @@ impl<'a> Linker for WasmLd<'a> {

fn no_relro(&mut self) {}

fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
self.cmd.arg("-l").arg(lib);
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
panic!("frameworks not supported")
}

fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive");
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
}

fn gc_sections(&mut self, _keep_metadata: bool) {
self.cmd.arg("--gc-sections");
}
@@ -1398,17 +1376,40 @@ pub struct L4Bender<'a> {
}

impl<'a> Linker for L4Bender<'a> {
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
bug!("dylibs are not supported on L4Re");
}
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {

fn link_staticlib_by_name(
&mut self,
name: &str,
_verbatim: bool,
whole_archive: bool,
_search_paths: &SearchPaths,
) {
self.hint_static();
self.cmd.arg(format!("-PC{lib}"));
if !whole_archive {
self.cmd.arg(format!("-PC{name}"));
} else {
self.cmd.arg("--whole-archive").arg(format!("-l{name}")).arg("--no-whole-archive");
}
}
fn link_rlib(&mut self, lib: &Path) {

fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
self.hint_static();
self.cmd.arg(lib);
if !whole_archive {
self.cmd.arg(path);
} else {
self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive");
}
}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}
@@ -1436,31 +1437,6 @@ impl<'a> Linker for L4Bender<'a> {
self.cmd.arg("-z").arg("norelro");
}

fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn link_rust_dylib(&mut self, _: &str, _: &Path) {
panic!("Rust dylibs not supported");
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
bug!("frameworks not supported on L4Re");
}

fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
self.hint_static();
self.cmd.arg("--whole-archive").arg(format!("-l{lib}"));
self.cmd.arg("--no-whole-archive");
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
}

fn gc_sections(&mut self, keep_metadata: bool) {
if !keep_metadata {
self.cmd.arg("--gc-sections");
@@ -1571,19 +1547,56 @@ impl<'a> AixLinker<'a> {
}

impl<'a> Linker for AixLinker<'a> {
fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) {
fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
match output_kind {
LinkOutputKind::DynamicDylib => {
self.hint_dynamic();
self.build_dylib(out_filename);
}
LinkOutputKind::StaticDylib => {
self.hint_static();
self.build_dylib(out_filename);
}
_ => {}
}
}

fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
self.hint_dynamic();
self.cmd.arg(format!("-l{lib}"));
self.cmd.arg(format!("-l{name}"));
}

fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
fn link_staticlib_by_name(
&mut self,
name: &str,
verbatim: bool,
whole_archive: bool,
search_paths: &SearchPaths,
) {
self.hint_static();
self.cmd.arg(format!("-l{lib}"));
if !whole_archive {
self.cmd.arg(format!("-l{name}"));
} else {
let mut arg = OsString::from("-bkeepfile:");
let search_path = search_paths.get(self.sess);
arg.push(find_native_static_library(name, verbatim, search_path, self.sess));
self.cmd.arg(arg);
}
}

fn link_rlib(&mut self, lib: &Path) {
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
self.hint_static();
self.cmd.arg(lib);
if !whole_archive {
self.cmd.arg(path);
} else {
let mut arg = OsString::from("-bkeepfile:");
arg.push(path);
self.cmd.arg(arg);
}
}

fn include_path(&mut self, path: &Path) {
@@ -1608,44 +1621,6 @@ impl<'a> Linker for AixLinker<'a> {

fn no_relro(&mut self) {}

fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
match output_kind {
LinkOutputKind::DynamicDylib => {
self.hint_dynamic();
self.build_dylib(out_filename);
}
LinkOutputKind::StaticDylib => {
self.hint_static();
self.build_dylib(out_filename);
}
_ => {}
}
}

fn link_rust_dylib(&mut self, lib: &str, _: &Path) {
self.hint_dynamic();
self.cmd.arg(format!("-l{lib}"));
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
bug!("frameworks not supported on AIX");
}

fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
self.hint_static();
let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap()));
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap()));
}

fn gc_sections(&mut self, _keep_metadata: bool) {
self.cmd.arg("-bgc");
}
@@ -1810,11 +1785,21 @@ impl<'a> Linker for PtxLinker<'a> {

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn link_rlib(&mut self, path: &Path) {
self.cmd.arg("--rlib").arg(path);
fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
panic!("external dylibs not supported")
}

fn link_staticlib_by_name(
&mut self,
_name: &str,
_verbatim: bool,
_whole_archive: bool,
_search_paths: &SearchPaths,
) {
panic!("staticlibs not supported")
}

fn link_whole_rlib(&mut self, path: &Path) {
fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
self.cmd.arg("--rlib").arg(path);
}

@@ -1844,30 +1829,10 @@ impl<'a> Linker for PtxLinker<'a> {
self.cmd.arg("-o").arg(path);
}

fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
panic!("external dylibs not supported")
}

fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
panic!("external dylibs not supported")
}

fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) {
panic!("staticlibs not supported")
}

fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
panic!("staticlibs not supported")
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks not supported")
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
panic!("frameworks not supported")
}

fn full_relro(&mut self) {}

fn partial_relro(&mut self) {}
@@ -1907,11 +1872,21 @@ impl<'a> Linker for BpfLinker<'a> {

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn link_rlib(&mut self, path: &Path) {
self.cmd.arg(path);
fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
panic!("external dylibs not supported")
}

fn link_whole_rlib(&mut self, path: &Path) {
fn link_staticlib_by_name(
&mut self,
_name: &str,
_verbatim: bool,
_whole_archive: bool,
_search_paths: &SearchPaths,
) {
panic!("staticlibs not supported")
}

fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
self.cmd.arg(path);
}

@@ -1942,30 +1917,10 @@ impl<'a> Linker for BpfLinker<'a> {
self.cmd.arg("-o").arg(path);
}

fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
panic!("external dylibs not supported")
}

fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
panic!("external dylibs not supported")
}

fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) {
panic!("staticlibs not supported")
}

fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
panic!("staticlibs not supported")
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks not supported")
}

fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
panic!("frameworks not supported")
}

fn full_relro(&mut self) {}

fn partial_relro(&mut self) {}