Skip to content

Commit 83cf265

Browse files
committed
Auto merge of #128370 - petrochenkov:libsearch, r=bjorn3
linker: Pass fewer search directories to the linker - The logic for passing `-L` directories to the linker is consolidated in a single function, so the search priorities are immediately clear. - Only `-Lnative=`, `-Lframework=` `-Lall=` directories are passed to linker, but not `-Lcrate=` and others. That's because only native libraries are looked up by name by linker, all Rust crates are passed using full paths, and their directories should not interfere with linker search paths. - The main sysroot library directory shouldn't generally be passed because it shouldn't contain native libraries, except for one case which is now marked with a FIXME. - This also helps with #123436, in which we need to walk the same list of directories manually. The next step is to migrate `find_native_static_library` to exactly the same set and order of search directories (which may be a bit annoying for the `iOSSupport` directories #121430 (comment)).
2 parents fd8d6fb + a83783a commit 83cf265

File tree

2 files changed

+61
-38
lines changed

2 files changed

+61
-38
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+56-38
Original file line numberDiff line numberDiff line change
@@ -2065,17 +2065,57 @@ fn add_local_crate_metadata_objects(
20652065
}
20662066

20672067
/// Add sysroot and other globally set directories to the directory search list.
2068-
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
2069-
// The default library location, we need this to find the runtime.
2070-
// The location of crates will be determined as needed.
2071-
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
2072-
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
2068+
fn add_library_search_dirs(
2069+
cmd: &mut dyn Linker,
2070+
sess: &Session,
2071+
self_contained_components: LinkSelfContainedComponents,
2072+
apple_sdk_root: Option<&Path>,
2073+
) {
2074+
if !sess.opts.unstable_opts.link_native_libraries {
2075+
return;
2076+
}
20732077

2074-
// Special directory with libraries used only in self-contained linkage mode
2075-
if self_contained {
2076-
let lib_path = sess.target_filesearch(PathKind::All).get_self_contained_lib_path();
2078+
// Library search paths explicitly supplied by user (`-L` on the command line).
2079+
for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() {
2080+
cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir));
2081+
}
2082+
for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() {
2083+
// Contrary to the `-L` docs only framework-specific paths are considered here.
2084+
if search_path.kind != PathKind::All {
2085+
cmd.framework_path(&search_path.dir);
2086+
}
2087+
}
2088+
2089+
// The toolchain ships some native library components and self-contained linking was enabled.
2090+
// Add the self-contained library directory to search paths.
2091+
if self_contained_components.intersects(
2092+
LinkSelfContainedComponents::LIBC
2093+
| LinkSelfContainedComponents::UNWIND
2094+
| LinkSelfContainedComponents::MINGW,
2095+
) {
2096+
let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path();
20772097
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
20782098
}
2099+
2100+
// Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
2101+
// library directory instead of the self-contained directories.
2102+
// The targets here should be in sync with `copy_third_party_objects` in bootstrap.
2103+
// FIXME: implement `-Clink-self-contained=+/-unwind`, move the shipped libunwind
2104+
// to self-contained directory, and stop adding this search path.
2105+
if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia"
2106+
{
2107+
let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path();
2108+
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
2109+
}
2110+
2111+
// Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
2112+
// we must have the support library stubs in the library search path (#121430).
2113+
if let Some(sdk_root) = apple_sdk_root
2114+
&& sess.target.llvm_target.contains("macabi")
2115+
{
2116+
cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
2117+
cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
2118+
}
20792119
}
20802120

20812121
/// Add options making relocation sections in the produced ELF files read-only
@@ -2367,7 +2407,7 @@ fn add_order_independent_options(
23672407
// Take care of the flavors and CLI options requesting the `lld` linker.
23682408
add_lld_args(cmd, sess, flavor, self_contained_components);
23692409

2370-
add_apple_sdk(cmd, sess, flavor);
2410+
let apple_sdk_root = add_apple_sdk(cmd, sess, flavor);
23712411

23722412
add_link_script(cmd, sess, tmpdir, crate_type);
23732413

@@ -2423,7 +2463,7 @@ fn add_order_independent_options(
24232463

24242464
cmd.linker_plugin_lto();
24252465

2426-
add_library_search_dirs(cmd, sess, self_contained_components.are_any_components_enabled());
2466+
add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref());
24272467

24282468
cmd.output_filename(out_filename);
24292469

@@ -2637,19 +2677,6 @@ fn add_local_native_libraries(
26372677
tmpdir: &Path,
26382678
link_output_kind: LinkOutputKind,
26392679
) {
2640-
if sess.opts.unstable_opts.link_native_libraries {
2641-
// User-supplied library search paths (-L on the command line). These are the same paths
2642-
// used to find Rust crates, so some of them may have been added already by the previous
2643-
// crate linking code. This only allows them to be found at compile time so it is still
2644-
// entirely up to outside forces to make sure that library can be found at runtime.
2645-
for search_path in sess.target_filesearch(PathKind::All).search_paths() {
2646-
match search_path.kind {
2647-
PathKind::Framework => cmd.framework_path(&search_path.dir),
2648-
_ => cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)),
2649-
}
2650-
}
2651-
}
2652-
26532680
// All static and dynamic native library dependencies are linked to the local crate.
26542681
let link_static = true;
26552682
let link_dynamic = true;
@@ -2944,19 +2971,19 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool
29442971
}
29452972
}
29462973

2947-
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
2974+
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
29482975
let arch = &sess.target.arch;
29492976
let os = &sess.target.os;
29502977
let llvm_target = &sess.target.llvm_target;
29512978
if sess.target.vendor != "apple"
29522979
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
29532980
|| !matches!(flavor, LinkerFlavor::Darwin(..))
29542981
{
2955-
return;
2982+
return None;
29562983
}
29572984

29582985
if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) {
2959-
return;
2986+
return None;
29602987
}
29612988

29622989
let sdk_name = match (arch.as_ref(), os.as_ref()) {
@@ -2980,14 +3007,14 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
29803007
(_, "macos") => "macosx",
29813008
_ => {
29823009
sess.dcx().emit_err(errors::UnsupportedArch { arch, os });
2983-
return;
3010+
return None;
29843011
}
29853012
};
29863013
let sdk_root = match get_apple_sdk_root(sdk_name) {
29873014
Ok(s) => s,
29883015
Err(e) => {
29893016
sess.dcx().emit_err(e);
2990-
return;
3017+
return None;
29913018
}
29923019
};
29933020

@@ -3007,16 +3034,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
30073034
_ => unreachable!(),
30083035
}
30093036

3010-
if llvm_target.contains("macabi") {
3011-
// Mac Catalyst uses the macOS SDK, but to link to iOS-specific
3012-
// frameworks, we must have the support library stubs in the library
3013-
// search path.
3014-
3015-
// The flags are called `-L` and `-F` both in Clang, ld64 and ldd.
3016-
let sdk_root = Path::new(&sdk_root);
3017-
cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
3018-
cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
3019-
}
3037+
Some(sdk_root.into())
30203038
}
30213039

30223040
fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> {

compiler/rustc_session/src/filesearch.rs

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ pub struct FileSearch<'a> {
1919
}
2020

2121
impl<'a> FileSearch<'a> {
22+
pub fn cli_search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
23+
let kind = self.kind;
24+
self.cli_search_paths.iter().filter(move |sp| sp.kind.matches(kind))
25+
}
26+
2227
pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
2328
let kind = self.kind;
2429
self.cli_search_paths

0 commit comments

Comments
 (0)