Skip to content

Commit e1ab664

Browse files
committed
linker: Move native library search from linker to rustc
For static libraries only, for now. Linker's search by name is still used if rustc's search fails, because linker may search in additional platform-specific directories in addition to directories known to rustc.
1 parent 42245d3 commit e1ab664

File tree

4 files changed

+33
-23
lines changed

4 files changed

+33
-23
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use std::{env, io, iter, mem, str};
66

77
use cc::windows_registry;
88
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
9-
use rustc_metadata::{
10-
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
11-
};
9+
use rustc_metadata::{try_find_native_dynamic_library, try_find_native_static_library};
1210
use rustc_middle::bug;
1311
use rustc_middle::middle::dependency_format::Linkage;
1412
use rustc_middle::middle::exported_symbols;
@@ -615,15 +613,15 @@ impl<'a> Linker for GccLinker<'a> {
615613
}
616614

617615
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
616+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
617+
return self.link_staticlib_by_path(&path, whole_archive);
618+
}
618619
self.hint_static();
619620
let colon = if verbatim && self.is_gnu { ":" } else { "" };
620621
if !whole_archive {
621622
self.link_or_cc_arg(format!("-l{colon}{name}"));
622623
} else if self.sess.target.is_like_darwin {
623-
// -force_load is the macOS equivalent of --whole-archive, but it
624-
// involves passing the full path to the library to link.
625-
self.link_arg("-force_load");
626-
self.link_arg(find_native_static_library(name, verbatim, self.sess));
624+
self.link_args(&["-force_load", name]);
627625
} else {
628626
self.link_arg("--whole-archive")
629627
.link_or_cc_arg(format!("-l{colon}{name}"))
@@ -956,15 +954,12 @@ impl<'a> Linker for MsvcLinker<'a> {
956954
}
957955

958956
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
959-
// On MSVC-like targets rustc supports static libraries using alternative naming
960-
// scheme (`libfoo.a`) unsupported by linker, search for such libraries manually.
961957
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
962-
self.link_staticlib_by_path(&path, whole_archive);
963-
} else {
964-
let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
965-
let (prefix, suffix) = self.sess.staticlib_components(verbatim);
966-
self.link_arg(format!("{opts}{prefix}{name}{suffix}"));
958+
return self.link_staticlib_by_path(&path, whole_archive);
967959
}
960+
let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
961+
let (prefix, suffix) = self.sess.staticlib_components(verbatim);
962+
self.link_arg(format!("{opts}{prefix}{name}{suffix}"));
968963
}
969964

970965
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
@@ -1193,7 +1188,10 @@ impl<'a> Linker for EmLinker<'a> {
11931188
self.link_or_cc_arg(path);
11941189
}
11951190

1196-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) {
1191+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1192+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1193+
return self.link_staticlib_by_path(&path, whole_archive);
1194+
}
11971195
self.link_or_cc_args(&["-l", name]);
11981196
}
11991197

@@ -1359,7 +1357,10 @@ impl<'a> Linker for WasmLd<'a> {
13591357
self.link_or_cc_arg(path);
13601358
}
13611359

1362-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1360+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1361+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1362+
return self.link_staticlib_by_path(&path, whole_archive);
1363+
}
13631364
if !whole_archive {
13641365
self.link_or_cc_args(&["-l", name]);
13651366
} else {
@@ -1493,7 +1494,10 @@ impl<'a> Linker for L4Bender<'a> {
14931494
) {
14941495
}
14951496

1496-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1497+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1498+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1499+
return self.link_staticlib_by_path(&path, whole_archive);
1500+
}
14971501
self.hint_static();
14981502
if !whole_archive {
14991503
self.link_arg(format!("-PC{name}"));
@@ -1667,12 +1671,15 @@ impl<'a> Linker for AixLinker<'a> {
16671671
}
16681672

16691673
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1674+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1675+
return self.link_staticlib_by_path(&path, whole_archive);
1676+
}
16701677
self.hint_static();
16711678
if !whole_archive {
16721679
self.link_or_cc_arg(if verbatim { String::from(name) } else { format!("-l{name}") });
16731680
} else {
16741681
let mut arg = OsString::from("-bkeepfile:");
1675-
arg.push(find_native_static_library(name, verbatim, self.sess));
1682+
arg.push(name);
16761683
self.link_or_cc_arg(arg);
16771684
}
16781685
}

src/doc/rustc/src/command-line-arguments.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ The name used in a `link` attribute may be overridden using the form `-l
8282
ATTR_NAME:LINK_NAME` where `ATTR_NAME` is the name in the `link` attribute,
8383
and `LINK_NAME` is the name of the actual library that will be linked.
8484

85+
The compiler may attempt to search for the library in native library search directories
86+
(controlled by `-L`), and pass it to linker by full path if the search is successful.
87+
Otherwise the library will be passed to linker by name, so it can perform its own search.
88+
In some cases this enables use of alternative library naming schemes or `+verbatim` modifier
89+
even if they are not natively supported by linker.
90+
8591
[link-attribute]: ../reference/items/external-blocks.html#the-link-attribute
8692

8793
### Linking modifiers: `whole-archive`

tests/run-make/native-link-modifier-bundle/rmake.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fn main() {
6868
.crate_type("cdylib")
6969
.print("link-args")
7070
.run()
71-
.assert_stdout_not_contains(r#"-l[" ]*native-staticlib"#);
71+
.assert_stdout_not_contains("libnative-staticlib.a");
7272
llvm_nm()
7373
.input(dynamic_lib_name("cdylib_bundled"))
7474
.run()
@@ -81,7 +81,7 @@ fn main() {
8181
.crate_type("cdylib")
8282
.print("link-args")
8383
.run()
84-
.assert_stdout_contains_regex(r#"-l[" ]*native-staticlib"#);
84+
.assert_stdout_contains_regex(r"libnative-staticlib.a");
8585
llvm_nm()
8686
.input(dynamic_lib_name("cdylib_non_bundled"))
8787
.run()

tests/run-make/native-link-modifier-verbatim-linker/rmake.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
// See https://github.com/rust-lang/rust/issues/99425
55

66
//@ ignore-cross-compile
7-
//@ ignore-apple
8-
//@ ignore-wasm
9-
// Reason: linking fails due to the unusual ".ext" staticlib name.
107

118
use run_make_support::rustc;
129

0 commit comments

Comments
 (0)