Skip to content

Commit 2e3f517

Browse files
committed
Add unstable rustc option to control self-contained linkage mode
1 parent 1557fb0 commit 2e3f517

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

src/librustc_codegen_ssa/back/link.rs

+37-17
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,12 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
140140
// The third parameter is for env vars, used on windows to set up the
141141
// path for MSVC to find its DLLs, and gcc to find its bundled
142142
// toolchain
143-
fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> Command {
143+
fn get_linker(
144+
sess: &Session,
145+
linker: &Path,
146+
flavor: LinkerFlavor,
147+
self_contained: bool,
148+
) -> Command {
144149
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
145150

146151
// If our linker looks like a batch script on Windows then to execute this
@@ -199,7 +204,7 @@ fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> Command {
199204

200205
// The compiler's sysroot often has some bundled tools, so add it to the
201206
// PATH for the child.
202-
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
207+
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
203208
let mut msvc_changed_path = false;
204209
if sess.target.target.options.is_like_msvc {
205210
if let Some(ref tool) = msvc_tool {
@@ -563,7 +568,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
563568
.iter()
564569
.copied()
565570
.flatten()
566-
.map(|obj| get_object_file_path(sess, obj).into_os_string())
571+
.map(|obj| get_object_file_path(sess, obj, fallback).into_os_string())
567572
.collect::<Vec<_>>()
568573
};
569574
let pre_objects_static_pie = get_objects(pre_objects, LinkOutputKind::StaticPicExe);
@@ -1066,9 +1071,11 @@ fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
10661071
}
10671072
}
10681073

1069-
fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
1074+
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
10701075
// prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
1071-
if sess.target.target.llvm_target.contains("windows-gnu") {
1076+
if sess.opts.debugging_opts.link_self_contained.is_none()
1077+
&& sess.target.target.llvm_target.contains("windows-gnu")
1078+
{
10721079
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
10731080
let file_path = compiler_libs_path.join(name);
10741081
if file_path.exists() {
@@ -1081,9 +1088,12 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
10811088
if file_path.exists() {
10821089
return file_path;
10831090
}
1084-
let file_path = fs.get_selfcontained_lib_path().join(name);
1085-
if file_path.exists() {
1086-
return file_path;
1091+
// Special directory with objects used only in self-contained linkage mode
1092+
if self_contained {
1093+
let file_path = fs.get_selfcontained_lib_path().join(name);
1094+
if file_path.exists() {
1095+
return file_path;
1096+
}
10871097
}
10881098
for search_path in fs.search_paths() {
10891099
let file_path = search_path.dir.join(name);
@@ -1268,6 +1278,10 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
12681278
/// Whether we link to our own CRT objects instead of relying on gcc to pull them.
12691279
/// We only provide such support for a very limited number of targets.
12701280
fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
1281+
if let Some(self_contained) = sess.opts.debugging_opts.link_self_contained {
1282+
return self_contained;
1283+
}
1284+
12711285
match sess.target.target.options.crt_objects_fallback {
12721286
// FIXME: Find a better heuristic for "native musl toolchain is available",
12731287
// based on host and linker path, for example.
@@ -1292,7 +1306,7 @@ fn add_pre_link_objects(
12921306
let opts = &sess.target.target.options;
12931307
let objects = if fallback { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects };
12941308
for obj in objects.get(&link_output_kind).iter().copied().flatten() {
1295-
cmd.add_object(&get_object_file_path(sess, obj));
1309+
cmd.add_object(&get_object_file_path(sess, obj, fallback));
12961310
}
12971311
}
12981312

@@ -1306,7 +1320,7 @@ fn add_post_link_objects(
13061320
let opts = &sess.target.target.options;
13071321
let objects = if fallback { &opts.post_link_objects_fallback } else { &opts.post_link_objects };
13081322
for obj in objects.get(&link_output_kind).iter().copied().flatten() {
1309-
cmd.add_object(&get_object_file_path(sess, obj));
1323+
cmd.add_object(&get_object_file_path(sess, obj, fallback));
13101324
}
13111325
}
13121326

@@ -1468,9 +1482,12 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'
14681482
}
14691483

14701484
/// Add sysroot and other globally set directories to the directory search list.
1471-
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
1485+
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
14721486
// Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details.
1473-
if cfg!(windows) && sess.target.target.llvm_target.contains("windows-gnu") {
1487+
if sess.opts.debugging_opts.link_self_contained.is_none()
1488+
&& cfg!(windows)
1489+
&& sess.target.target.llvm_target.contains("windows-gnu")
1490+
{
14741491
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
14751492
cmd.include_path(&compiler_libs_path);
14761493
}
@@ -1481,8 +1498,11 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
14811498
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
14821499
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
14831500

1484-
let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path();
1485-
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
1501+
// Special directory with libraries used only in self-contained linkage mode
1502+
if self_contained {
1503+
let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path();
1504+
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
1505+
}
14861506
}
14871507

14881508
/// Add options making relocation sections in the produced ELF files read-only
@@ -1545,13 +1565,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15451565
codegen_results: &CodegenResults,
15461566
target_cpu: &str,
15471567
) -> Command {
1548-
let base_cmd = get_linker(sess, path, flavor);
1568+
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
1569+
let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
15491570
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
15501571
// to the linker args construction.
15511572
assert!(base_cmd.get_args().is_empty() || sess.target.target.target_vendor == "uwp");
15521573
let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor, target_cpu);
15531574
let link_output_kind = link_output_kind(sess, crate_type);
1554-
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
15551575

15561576
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
15571577
add_pre_link_args(cmd, sess, flavor);
@@ -1597,7 +1617,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15971617

15981618
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
15991619
// FIXME: Order-dependent, at least relatively to other args adding searh directories.
1600-
add_library_search_dirs(cmd, sess);
1620+
add_library_search_dirs(cmd, sess, crt_objects_fallback);
16011621

16021622
// OBJECT-FILES-YES
16031623
add_local_crate_regular_objects(cmd, codegen_results);

src/librustc_session/filesearch.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ impl<'a> FileSearch<'a> {
9292
}
9393

9494
// Returns a list of directories where target-specific tool binaries are located.
95-
pub fn get_tools_search_paths(&self) -> Vec<PathBuf> {
95+
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
9696
let mut p = PathBuf::from(self.sysroot);
9797
p.push(find_libdir(self.sysroot).as_ref());
9898
p.push(RUST_LIB_DIR);
9999
p.push(&self.triple);
100100
p.push("bin");
101-
vec![p.clone(), p.join("self-contained")]
101+
if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p.clone()] }
102102
}
103103
}
104104

src/librustc_session/options.rs

+3
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
888888
"keep hygiene data after analysis (default: no)"),
889889
link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
890890
"link native libraries in the linker invocation (default: yes)"),
891+
link_self_contained: Option<bool> = (None, parse_opt_bool, [TRACKED],
892+
"control whether to link Rust provided C objects/libraries or rely
893+
on C toolchain installed in the system"),
891894
link_only: bool = (false, parse_bool, [TRACKED],
892895
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
893896
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],

0 commit comments

Comments
 (0)