Skip to content

Commit aa5028d

Browse files
committed
linker: Synchronize native library search in rustc and linker
1 parent 982c6f8 commit aa5028d

File tree

3 files changed

+97
-57
lines changed

3 files changed

+97
-57
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1818
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
1919
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
2020
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
21-
use rustc_metadata::find_native_static_library;
2221
use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
22+
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
2323
use rustc_middle::bug;
2424
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
2525
use rustc_middle::middle::dependency_format::Linkage;
@@ -2113,51 +2113,19 @@ fn add_library_search_dirs(
21132113
return;
21142114
}
21152115

2116-
// Library search paths explicitly supplied by user (`-L` on the command line).
2117-
for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() {
2118-
cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir));
2119-
}
2120-
for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() {
2121-
// Contrary to the `-L` docs only framework-specific paths are considered here.
2122-
if search_path.kind != PathKind::All {
2123-
cmd.framework_path(&search_path.dir);
2124-
}
2125-
}
2126-
2127-
// The toolchain ships some native library components and self-contained linking was enabled.
2128-
// Add the self-contained library directory to search paths.
2129-
if self_contained_components.intersects(
2130-
LinkSelfContainedComponents::LIBC
2131-
| LinkSelfContainedComponents::UNWIND
2132-
| LinkSelfContainedComponents::MINGW,
2133-
) {
2134-
let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path();
2135-
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
2136-
}
2137-
2138-
// Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
2139-
// library directory instead of the self-contained directories.
2140-
// Sanitizer libraries have the same issue and are also linked by name on Apple targets.
2141-
// The targets here should be in sync with `copy_third_party_objects` in bootstrap.
2142-
// FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
2143-
// and sanitizers to self-contained directory, and stop adding this search path.
2144-
if sess.target.vendor == "fortanix"
2145-
|| sess.target.os == "linux"
2146-
|| sess.target.os == "fuchsia"
2147-
|| sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty()
2148-
{
2149-
let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path();
2150-
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
2151-
}
2152-
2153-
// Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
2154-
// we must have the support library stubs in the library search path (#121430).
2155-
if let Some(sdk_root) = apple_sdk_root
2156-
&& sess.target.llvm_target.contains("macabi")
2157-
{
2158-
cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
2159-
cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
2160-
}
2116+
walk_native_lib_search_dirs(
2117+
sess,
2118+
self_contained_components,
2119+
apple_sdk_root,
2120+
|dir, is_framework| {
2121+
if is_framework {
2122+
cmd.framework_path(dir);
2123+
} else {
2124+
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
2125+
}
2126+
None::<()>
2127+
},
2128+
);
21612129
}
21622130

21632131
/// Add options making relocation sections in the produced ELF files read-only

compiler/rustc_metadata/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ pub mod locator;
3434

3535
pub use creader::{load_symbol_from_dylib, DylibError};
3636
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
37-
pub use native_libs::find_native_static_library;
37+
pub use native_libs::{
38+
find_native_static_library, try_find_native_static_library, walk_native_lib_search_dirs,
39+
};
3840
pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER};
3941

4042
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::path::PathBuf;
1+
use std::path::{Path, PathBuf};
22

33
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
44
use rustc_attr as attr;
@@ -16,10 +16,68 @@ use rustc_session::Session;
1616
use rustc_span::def_id::{DefId, LOCAL_CRATE};
1717
use rustc_span::symbol::{sym, Symbol};
1818
use rustc_target::spec::abi::Abi;
19+
use rustc_target::spec::LinkSelfContainedComponents;
1920

2021
use crate::{errors, fluent_generated};
2122

22-
pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
23+
pub fn walk_native_lib_search_dirs<R>(
24+
sess: &Session,
25+
self_contained_components: LinkSelfContainedComponents,
26+
apple_sdk_root: Option<&Path>,
27+
mut f: impl FnMut(&Path, bool /*is_framework*/) -> Option<R>,
28+
) -> Option<R> {
29+
// Library search paths explicitly supplied by user (`-L` on the command line).
30+
for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() {
31+
f(&search_path.dir, false)?;
32+
}
33+
for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() {
34+
// Contrary to the `-L` docs only framework-specific paths are considered here.
35+
if search_path.kind != PathKind::All {
36+
f(&search_path.dir, true)?;
37+
}
38+
}
39+
40+
// The toolchain ships some native library components and self-contained linking was enabled.
41+
// Add the self-contained library directory to search paths.
42+
if self_contained_components.intersects(
43+
LinkSelfContainedComponents::LIBC
44+
| LinkSelfContainedComponents::UNWIND
45+
| LinkSelfContainedComponents::MINGW,
46+
) {
47+
f(&sess.target_filesearch(PathKind::Native).get_self_contained_lib_path(), false)?;
48+
}
49+
50+
// Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
51+
// library directory instead of the self-contained directories.
52+
// Sanitizer libraries have the same issue and are also linked by name on Apple targets.
53+
// The targets here should be in sync with `copy_third_party_objects` in bootstrap.
54+
// FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
55+
// and sanitizers to self-contained directory, and stop adding this search path.
56+
if sess.target.vendor == "fortanix"
57+
|| sess.target.os == "linux"
58+
|| sess.target.os == "fuchsia"
59+
|| sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty()
60+
{
61+
f(&sess.target_filesearch(PathKind::Native).get_lib_path(), false)?;
62+
}
63+
64+
// Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
65+
// we must have the support library stubs in the library search path (#121430).
66+
if let Some(sdk_root) = apple_sdk_root
67+
&& sess.target.llvm_target.contains("macabi")
68+
{
69+
f(&sdk_root.join("System/iOSSupport/usr/lib"), false)?;
70+
f(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"), true)?;
71+
}
72+
73+
None
74+
}
75+
76+
pub fn try_find_native_static_library(
77+
sess: &Session,
78+
name: &str,
79+
verbatim: bool,
80+
) -> Option<PathBuf> {
2381
let formats = if verbatim {
2482
vec![("".into(), "".into())]
2583
} else {
@@ -30,16 +88,28 @@ pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) ->
3088
if os == unix { vec![os] } else { vec![os, unix] }
3189
};
3290

33-
for path in sess.target_filesearch(PathKind::Native).search_paths() {
34-
for (prefix, suffix) in &formats {
35-
let test = path.dir.join(format!("{prefix}{name}{suffix}"));
36-
if test.exists() {
37-
return test;
91+
// FIXME: Account for self-contained linking settings and Apple SDK.
92+
walk_native_lib_search_dirs(
93+
sess,
94+
LinkSelfContainedComponents::empty(),
95+
None,
96+
|dir, is_framework| {
97+
if !is_framework {
98+
for (prefix, suffix) in &formats {
99+
let test = dir.join(format!("{prefix}{name}{suffix}"));
100+
if test.exists() {
101+
return Some(test);
102+
}
103+
}
38104
}
39-
}
40-
}
105+
None
106+
},
107+
)
108+
}
41109

42-
sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim));
110+
pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
111+
try_find_native_static_library(sess, name, verbatim)
112+
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))
43113
}
44114

45115
fn find_bundled_library(

0 commit comments

Comments
 (0)