@@ -11,7 +11,9 @@ use rustc_session::search_paths::PathKind;
11
11
/// need out of the shared crate context before we get rid of it.
12
12
use rustc_session::{filesearch, Session};
13
13
use rustc_span::symbol::Symbol;
14
- use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel};
14
+ use rustc_target::spec::crt_objects::CrtObjectsFallback;
15
+ use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
16
+ use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel};
15
17
16
18
use super::archive::ArchiveBuilder;
17
19
use super::command::Command;
@@ -1130,33 +1132,70 @@ fn exec_linker(
1130
1132
}
1131
1133
}
1132
1134
1133
- /// Add begin object files defined by the target spec.
1134
- fn add_pre_link_objects(cmd: &mut dyn Linker, sess: &Session, crate_type: CrateType) {
1135
- let pre_link_objects = if crate_type == CrateType::Executable {
1136
- &sess.target.target.options.pre_link_objects_exe
1137
- } else {
1138
- &sess.target.target.options.pre_link_objects_dll
1135
+ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
1136
+ let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
1137
+ (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
1138
+ (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
1139
+ (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
1140
+ (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe,
1141
+ (_, true, _) => LinkOutputKind::StaticDylib,
1142
+ (_, false, _) => LinkOutputKind::DynamicDylib,
1139
1143
};
1140
- for obj in pre_link_objects {
1141
- cmd.add_object(&get_object_file_path(sess, obj));
1144
+
1145
+ // Adjust the output kind to target capabilities.
1146
+ let pic_exe_supported = sess.target.target.options.position_independent_executables;
1147
+ let static_pic_exe_supported = false; // FIXME: Add this option to target specs.
1148
+ let static_dylib_supported = sess.target.target.options.crt_static_allows_dylibs;
1149
+ match kind {
1150
+ LinkOutputKind::DynamicPicExe if !pic_exe_supported => LinkOutputKind::DynamicNoPicExe,
1151
+ LinkOutputKind::StaticPicExe if !static_pic_exe_supported => LinkOutputKind::StaticNoPicExe,
1152
+ LinkOutputKind::StaticDylib if !static_dylib_supported => LinkOutputKind::DynamicDylib,
1153
+ _ => kind,
1142
1154
}
1155
+ }
1143
1156
1144
- if crate_type == CrateType::Executable && sess.crt_static(Some(crate_type)) {
1145
- for obj in &sess.target.target.options.pre_link_objects_exe_crt {
1146
- cmd.add_object(&get_object_file_path(sess, obj));
1147
- }
1157
+ /// Whether we link to our own CRT objects instead of relying on gcc to pull them.
1158
+ /// We only provide such support for a very limited number of targets.
1159
+ fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
1160
+ match sess.target.target.options.crt_objects_fallback {
1161
+ // FIXME: Find a better heuristic for "native musl toolchain is available",
1162
+ // based on host and linker path, for example.
1163
+ // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
1164
+ Some(CrtObjectsFallback::Musl) => sess.crt_static(Some(crate_type)),
1165
+ // FIXME: Find some heuristic for "native mingw toolchain is available",
1166
+ // likely based on `get_crt_libs_path` (https://github.com/rust-lang/rust/pull/67429).
1167
+ Some(CrtObjectsFallback::Mingw) => sess.target.target.target_vendor != "uwp",
1168
+ // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
1169
+ Some(CrtObjectsFallback::Wasm) => true,
1170
+ None => false,
1148
1171
}
1149
1172
}
1150
1173
1151
- /// Add end object files defined by the target spec.
1152
- fn add_post_link_objects(cmd: &mut dyn Linker, sess: &Session, crate_type: CrateType) {
1153
- for obj in &sess.target.target.options.post_link_objects {
1174
+ /// Add pre-link object files defined by the target spec.
1175
+ fn add_pre_link_objects(
1176
+ cmd: &mut dyn Linker,
1177
+ sess: &Session,
1178
+ link_output_kind: LinkOutputKind,
1179
+ fallback: bool,
1180
+ ) {
1181
+ let opts = &sess.target.target.options;
1182
+ let objects = if fallback { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects };
1183
+ for obj in objects.get(&link_output_kind).iter().copied().flatten() {
1154
1184
cmd.add_object(&get_object_file_path(sess, obj));
1155
1185
}
1156
- if sess.crt_static(Some(crate_type)) {
1157
- for obj in &sess.target.target.options.post_link_objects_crt {
1158
- cmd.add_object(&get_object_file_path(sess, obj));
1159
- }
1186
+ }
1187
+
1188
+ /// Add post-link object files defined by the target spec.
1189
+ fn add_post_link_objects(
1190
+ cmd: &mut dyn Linker,
1191
+ sess: &Session,
1192
+ link_output_kind: LinkOutputKind,
1193
+ fallback: bool,
1194
+ ) {
1195
+ let opts = &sess.target.target.options;
1196
+ let objects = if fallback { &opts.post_link_objects_fallback } else { &opts.post_link_objects };
1197
+ for obj in objects.get(&link_output_kind).iter().copied().flatten() {
1198
+ cmd.add_object(&get_object_file_path(sess, obj));
1160
1199
}
1161
1200
}
1162
1201
@@ -1342,38 +1381,6 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
1342
1381
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
1343
1382
}
1344
1383
1345
- /// Add options requesting executables to be position-independent or not position-independent.
1346
- fn add_position_independent_executable_args(
1347
- cmd: &mut dyn Linker,
1348
- sess: &Session,
1349
- flavor: LinkerFlavor,
1350
- crate_type: CrateType,
1351
- codegen_results: &CodegenResults,
1352
- ) {
1353
- if crate_type != CrateType::Executable {
1354
- return;
1355
- }
1356
-
1357
- if sess.target.target.options.position_independent_executables {
1358
- let attr_link_args = &*codegen_results.crate_info.link_args;
1359
- let mut user_defined_link_args = sess.opts.cg.link_args.iter().chain(attr_link_args);
1360
- if sess.relocation_model() == RelocModel::Pic
1361
- && !sess.crt_static(Some(crate_type))
1362
- && !user_defined_link_args.any(|x| x == "-static")
1363
- {
1364
- cmd.position_independent_executable();
1365
- return;
1366
- }
1367
- }
1368
-
1369
- // Recent versions of gcc can be configured to generate position
1370
- // independent executables by default. We have to pass -no-pie to
1371
- // explicitly turn that off. Not applicable to ld.
1372
- if sess.target.target.options.linker_is_gnu && flavor != LinkerFlavor::Ld {
1373
- cmd.no_position_independent_executable();
1374
- }
1375
- }
1376
-
1377
1384
/// Add options making relocation sections in the produced ELF files read-only
1378
1385
/// and suppressing lazy binding.
1379
1386
fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) {
@@ -1439,6 +1446,8 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1439
1446
// to the linker args construction.
1440
1447
assert!(base_cmd.get_args().is_empty() || sess.target.target.target_vendor == "uwp");
1441
1448
let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor, target_cpu);
1449
+ let link_output_kind = link_output_kind(sess, crate_type);
1450
+ let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
1442
1451
1443
1452
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
1444
1453
add_pre_link_args(cmd, sess, flavor, crate_type);
@@ -1455,8 +1464,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1455
1464
cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix));
1456
1465
}
1457
1466
1467
+ // NO-OPT-OUT, OBJECT-FILES-NO
1468
+ if crt_objects_fallback {
1469
+ cmd.no_crt_objects();
1470
+ }
1471
+
1458
1472
// NO-OPT-OUT, OBJECT-FILES-YES
1459
- add_pre_link_objects(cmd, sess, crate_type );
1473
+ add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback );
1460
1474
1461
1475
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1462
1476
if sess.target.target.options.is_like_emscripten {
@@ -1515,7 +1529,16 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1515
1529
}
1516
1530
1517
1531
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1518
- add_position_independent_executable_args(cmd, sess, flavor, crate_type, codegen_results);
1532
+ // FIXME: Support `StaticPicExe` correctly.
1533
+ match link_output_kind {
1534
+ LinkOutputKind::DynamicPicExe | LinkOutputKind::StaticPicExe => {
1535
+ cmd.position_independent_executable()
1536
+ }
1537
+ LinkOutputKind::DynamicNoPicExe | LinkOutputKind::StaticNoPicExe => {
1538
+ cmd.no_position_independent_executable()
1539
+ }
1540
+ _ => {}
1541
+ }
1519
1542
1520
1543
// OBJECT-FILES-NO, AUDIT-ORDER
1521
1544
add_relro_args(cmd, sess);
@@ -1545,12 +1568,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1545
1568
);
1546
1569
1547
1570
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1548
- // Tell the linker what we're doing.
1549
- if crate_type != CrateType::Executable {
1550
- cmd.build_dylib(out_filename);
1551
- }
1552
- if crate_type == CrateType::Executable && sess.crt_static(Some(crate_type)) {
1553
- cmd.build_static_executable();
1571
+ // FIXME: Merge with the previous `link_output_kind` match,
1572
+ // and support `StaticPicExe` and `StaticDylib` correctly.
1573
+ match link_output_kind {
1574
+ LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {
1575
+ cmd.build_static_executable()
1576
+ }
1577
+ LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => cmd.build_dylib(out_filename),
1578
+ _ => {}
1554
1579
}
1555
1580
1556
1581
// OBJECT-FILES-NO, AUDIT-ORDER
@@ -1576,7 +1601,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1576
1601
add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);
1577
1602
1578
1603
// NO-OPT-OUT, OBJECT-FILES-YES
1579
- add_post_link_objects(cmd, sess, crate_type );
1604
+ add_post_link_objects(cmd, sess, link_output_kind, crt_objects_fallback );
1580
1605
1581
1606
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
1582
1607
add_post_link_args(cmd, sess, flavor);
0 commit comments