linker: Refactor APIs for linking dynamic libraries

Rename `link_(dylib,framework)`, remove `link_rust_dylib`.
This commit is contained in:
Vadim Petrochenkov 2024-01-17 23:14:14 +03:00
parent 5d3d3479d7
commit 50501c6fba
2 changed files with 33 additions and 93 deletions

View File

@ -1265,7 +1265,7 @@ fn link_sanitizer_runtime(
let path = find_sanitizer_runtime(sess, &filename); let path = find_sanitizer_runtime(sess, &filename);
let rpath = path.to_str().expect("non-utf8 component in path"); let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); 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" { } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" {
// MSVC provides the `/INFERASANLIBS` argument to automatically find the // MSVC provides the `/INFERASANLIBS` argument to automatically find the
// compatible ASAN library. // compatible ASAN library.
@ -2526,7 +2526,7 @@ fn add_native_libs_from_crate(
} }
NativeLibKind::Dylib { as_needed } => { NativeLibKind::Dylib { as_needed } => {
if link_dynamic { 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 => { NativeLibKind::Unspecified => {
@ -2538,13 +2538,13 @@ fn add_native_libs_from_crate(
} }
} else { } else {
if link_dynamic { if link_dynamic {
cmd.link_dylib(name, verbatim, true); cmd.link_dylib_by_name(name, verbatim, true);
} }
} }
} }
NativeLibKind::Framework { as_needed } => { NativeLibKind::Framework { as_needed } => {
if link_dynamic { 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 => { NativeLibKind::RawDylib => {
@ -2859,13 +2859,20 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
// Just need to tell the linker about where the library lives and // Just need to tell the linker about where the library lives and
// what its name is // what its name is
let parent = cratepath.parent(); 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 { if let Some(dir) = parent {
cmd.include_path(&rehome_sysroot_lib_dir(sess, dir)); cmd.include_path(&rehome_sysroot_lib_dir(sess, dir));
} }
let stem = cratepath.file_stem().unwrap().to_str().unwrap(); let stem = cratepath.file_stem().unwrap().to_str().unwrap();
// Convert library file-stem into a cc -l argument. // Convert library file-stem into a cc -l argument.
let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 }; 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 { fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {

View File

@ -166,9 +166,10 @@ pub fn get_linker<'a>(
pub trait Linker { pub trait Linker {
fn cmd(&mut self) -> &mut Command; fn cmd(&mut self) -> &mut Command;
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path); 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_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool);
fn link_rust_dylib(&mut self, lib: &str, path: &Path); fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
fn link_framework(&mut self, framework: &str, as_needed: bool); bug!("framework linked with unsupported linker")
}
fn link_staticlib(&mut self, lib: &str, verbatim: bool); fn link_staticlib(&mut self, lib: &str, verbatim: bool);
fn link_rlib(&mut self, lib: &Path); fn link_rlib(&mut self, lib: &Path);
fn link_whole_rlib(&mut self, lib: &Path); fn link_whole_rlib(&mut self, lib: &Path);
@ -432,8 +433,8 @@ impl<'a> Linker for GccLinker<'a> {
} }
} }
fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool) { fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
if self.sess.target.os == "illumos" && lib == "c" { if self.sess.target.os == "illumos" && name == "c" {
// libc will be added via late_link_args on illumos so that it will // libc will be added via late_link_args on illumos so that it will
// appear last in the library search order. // appear last in the library search order.
// FIXME: This should be replaced by a more complete and generic // FIXME: This should be replaced by a more complete and generic
@ -454,7 +455,7 @@ impl<'a> Linker for GccLinker<'a> {
} }
} }
self.hint_dynamic(); 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 !as_needed {
if self.sess.target.is_like_osx { if self.sess.target.is_like_osx {
// See above FIXME comment // See above FIXME comment
@ -493,20 +494,15 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_args(&["-z", "norelro"]); self.linker_args(&["-z", "norelro"]);
} }
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) {
self.hint_dynamic();
self.cmd.arg(format!("-l{lib}"));
}
fn link_framework(&mut self, framework: &str, as_needed: bool) {
self.hint_dynamic(); self.hint_dynamic();
if !as_needed { if !as_needed {
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
// flag but we have no way to detect that here. // flag but we have no way to detect that here.
// self.cmd.arg("-needed_framework").arg(framework); // self.cmd.arg("-needed_framework").arg(name);
self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
} }
self.cmd.arg("-framework").arg(framework); self.cmd.arg("-framework").arg(name);
} }
// Here we explicitly ask that the entire archive is included into the // Here we explicitly ask that the entire archive is included into the
@ -845,19 +841,8 @@ impl<'a> Linker for MsvcLinker<'a> {
self.cmd.arg("/OPT:NOREF,NOICF"); self.cmd.arg("/OPT:NOREF,NOICF");
} }
fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" })); self.cmd.arg(format!("{}{}", name, 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) { fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
@ -899,9 +884,6 @@ impl<'a> Linker for MsvcLinker<'a> {
fn framework_path(&mut self, _path: &Path) { fn framework_path(&mut self, _path: &Path) {
bug!("frameworks are not supported on windows") 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]) { fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" })); self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" }));
@ -1073,9 +1055,9 @@ impl<'a> Linker for EmLinker<'a> {
self.cmd.arg(path); self.cmd.arg(path);
} }
fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
// Emscripten always links statically // Emscripten always links statically
self.link_staticlib(lib, verbatim); self.link_staticlib(name, verbatim);
} }
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) { fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
@ -1088,10 +1070,6 @@ impl<'a> Linker for EmLinker<'a> {
self.link_rlib(lib); self.link_rlib(lib);
} }
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
self.link_dylib(lib, false, true);
}
fn link_rlib(&mut self, lib: &Path) { fn link_rlib(&mut self, lib: &Path) {
self.add_object(lib); self.add_object(lib);
} }
@ -1112,10 +1090,6 @@ impl<'a> Linker for EmLinker<'a> {
bug!("frameworks are not supported on Emscripten") 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) { fn gc_sections(&mut self, _keep_metadata: bool) {
// noop // noop
} }
@ -1249,8 +1223,8 @@ impl<'a> Linker for WasmLd<'a> {
} }
} }
fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
self.cmd.arg("-l").arg(lib); self.cmd.arg("-l").arg(name);
} }
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
@ -1283,14 +1257,6 @@ impl<'a> Linker for WasmLd<'a> {
fn no_relro(&mut self) {} 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]) { 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"); self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive");
} }
@ -1398,7 +1364,7 @@ pub struct L4Bender<'a> {
} }
impl<'a> Linker for L4Bender<'a> { impl<'a> Linker for L4Bender<'a> {
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
bug!("dylibs are not supported on L4Re"); bug!("dylibs are not supported on L4Re");
} }
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
@ -1442,14 +1408,6 @@ impl<'a> Linker for L4Bender<'a> {
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} 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]) { fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
self.hint_static(); self.hint_static();
self.cmd.arg("--whole-archive").arg(format!("-l{lib}")); self.cmd.arg("--whole-archive").arg(format!("-l{lib}"));
@ -1571,9 +1529,9 @@ impl<'a> AixLinker<'a> {
} }
impl<'a> Linker for AixLinker<'a> { impl<'a> Linker for AixLinker<'a> {
fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
self.hint_dynamic(); 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(&mut self, lib: &str, _verbatim: bool) {
@ -1626,15 +1584,6 @@ impl<'a> Linker for AixLinker<'a> {
} }
} }
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]) { fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
self.hint_static(); self.hint_static();
let lib = find_native_static_library(lib, verbatim, search_path, self.sess); let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
@ -1844,11 +1793,7 @@ impl<'a> Linker for PtxLinker<'a> {
self.cmd.arg("-o").arg(path); self.cmd.arg("-o").arg(path);
} }
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, _name: &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") panic!("external dylibs not supported")
} }
@ -1864,10 +1809,6 @@ impl<'a> Linker for PtxLinker<'a> {
panic!("frameworks not supported") panic!("frameworks not supported")
} }
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
panic!("frameworks not supported")
}
fn full_relro(&mut self) {} fn full_relro(&mut self) {}
fn partial_relro(&mut self) {} fn partial_relro(&mut self) {}
@ -1942,11 +1883,7 @@ impl<'a> Linker for BpfLinker<'a> {
self.cmd.arg("-o").arg(path); self.cmd.arg("-o").arg(path);
} }
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { fn link_dylib_by_name(&mut self, _name: &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") panic!("external dylibs not supported")
} }
@ -1962,10 +1899,6 @@ impl<'a> Linker for BpfLinker<'a> {
panic!("frameworks not supported") panic!("frameworks not supported")
} }
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
panic!("frameworks not supported")
}
fn full_relro(&mut self) {} fn full_relro(&mut self) {}
fn partial_relro(&mut self) {} fn partial_relro(&mut self) {}