Skip to content

Commit 97efaa2

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 87e60a7 commit 97efaa2

File tree

4 files changed

+33
-23
lines changed

4 files changed

+33
-23
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

+25-18
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;
@@ -614,15 +612,15 @@ impl<'a> Linker for GccLinker<'a> {
614612
}
615613

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

955953
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
956-
// On MSVC-like targets rustc supports static libraries using alternative naming
957-
// scheme (`libfoo.a`) unsupported by linker, search for such libraries manually.
958954
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
959-
self.link_staticlib_by_path(&path, whole_archive);
960-
} else {
961-
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
962-
let suffix = if verbatim { "" } else { ".lib" };
963-
self.link_arg(format!("{prefix}{name}{suffix}"));
955+
return self.link_staticlib_by_path(&path, whole_archive);
964956
}
957+
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
958+
let suffix = if verbatim { "" } else { ".lib" };
959+
self.link_arg(format!("{prefix}{name}{suffix}"));
965960
}
966961

967962
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
@@ -1190,7 +1185,10 @@ impl<'a> Linker for EmLinker<'a> {
11901185
self.link_or_cc_arg(path);
11911186
}
11921187

1193-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) {
1188+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1189+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1190+
return self.link_staticlib_by_path(&path, whole_archive);
1191+
}
11941192
self.link_or_cc_args(&["-l", name]);
11951193
}
11961194

@@ -1356,7 +1354,10 @@ impl<'a> Linker for WasmLd<'a> {
13561354
self.link_or_cc_arg(path);
13571355
}
13581356

1359-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1357+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1358+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1359+
return self.link_staticlib_by_path(&path, whole_archive);
1360+
}
13601361
if !whole_archive {
13611362
self.link_or_cc_args(&["-l", name]);
13621363
} else {
@@ -1490,7 +1491,10 @@ impl<'a> Linker for L4Bender<'a> {
14901491
) {
14911492
}
14921493

1493-
fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1494+
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1495+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1496+
return self.link_staticlib_by_path(&path, whole_archive);
1497+
}
14941498
self.hint_static();
14951499
if !whole_archive {
14961500
self.link_arg(format!("-PC{name}"));
@@ -1664,12 +1668,15 @@ impl<'a> Linker for AixLinker<'a> {
16641668
}
16651669

16661670
fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1671+
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1672+
return self.link_staticlib_by_path(&path, whole_archive);
1673+
}
16671674
self.hint_static();
16681675
if !whole_archive {
16691676
self.link_or_cc_arg(if verbatim { String::from(name) } else { format!("-l{name}") });
16701677
} else {
16711678
let mut arg = OsString::from("-bkeepfile:");
1672-
arg.push(find_native_static_library(name, verbatim, self.sess));
1679+
arg.push(name);
16731680
self.link_or_cc_arg(arg);
16741681
}
16751682
}

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

+6
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

+2-2
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

-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
// This test is the same as native-link-modifier-rustc, but without rlibs.
44
// See https://github.com/rust-lang/rust/issues/99425
55

6-
//@ ignore-apple
7-
// Reason: linking fails due to the unusual ".ext" staticlib name.
8-
96
use run_make_support::rustc;
107

118
fn main() {

0 commit comments

Comments
 (0)