Skip to content

Commit 5aa23be

Browse files
committed
Auto merge of #116014 - lqd:mcp510-2-electric-boogaloo, r=petrochenkov
Implement `-Clink-self-contained=-linker` opt out This implements the `-Clink-self-contained` opt out necessary to switch to lld by changing rustc's defaults instead of cargo's. Components that are enabled and disabled on the CLI are recorded, for the purpose of being merged with the ones which the target spec will declare (I'll open another PR for that tomorrow, for easier review). For MCP510, we now check whether using the self-contained linker is disabled on the CLI. Right now it would only be sensible to with `-Zgcc-ld=lld` (and I'll add some checks that we don't both enable and disable a component on the CLI in a future PR), but the goal is to simplify adding the check of the target's enabled components here in the follow-up PRs. r? `@petrochenkov`
2 parents 71704c4 + d634cc5 commit 5aa23be

File tree

10 files changed

+159
-64
lines changed

10 files changed

+159
-64
lines changed

Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -4479,7 +4479,6 @@ dependencies = [
44794479
name = "rustc_session"
44804480
version = "0.0.0"
44814481
dependencies = [
4482-
"bitflags 1.3.2",
44834482
"getopts",
44844483
"libc",
44854484
"rustc_ast",

compiler/rustc_codegen_ssa/src/back/link.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2978,8 +2978,9 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
29782978
}
29792979

29802980
// 1. Implement the "self-contained" part of this feature by adding rustc distribution
2981-
// directories to the tool's search path.
2982-
if sess.opts.cg.link_self_contained.linker() {
2981+
// directories to the tool's search path:
2982+
// - if the self-contained linker is enabled on the CLI.
2983+
if sess.opts.cg.link_self_contained.is_linker_enabled() {
29832984
for path in sess.get_tools_search_paths(false) {
29842985
cmd.arg({
29852986
let mut arg = OsString::from("-B");
@@ -2990,7 +2991,7 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
29902991
}
29912992

29922993
// 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
2993-
// `lld` as the linker.
2994+
// `lld` as the linker.
29942995
cmd.arg("-fuse-ld=lld");
29952996

29962997
if !flavor.is_gnu() {

compiler/rustc_session/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ version = "0.0.0"
44
edition = "2021"
55

66
[dependencies]
7-
bitflags = "1.2.1"
87
getopts = "0.2"
98
rustc_macros = { path = "../rustc_macros" }
109
tracing = "0.1"

compiler/rustc_session/src/config.rs

+60-53
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{EarlyErrorHandler, Session};
1212
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1313
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
1414
use rustc_target::abi::Align;
15+
use rustc_target::spec::LinkSelfContainedComponents;
1516
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
1617
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
1718

@@ -232,75 +233,50 @@ pub struct LinkSelfContained {
232233
/// Used for compatibility with the existing opt-in and target inference.
233234
pub explicitly_set: Option<bool>,
234235

235-
/// The components that are enabled.
236-
components: LinkSelfContainedComponents,
237-
}
238-
239-
bitflags::bitflags! {
240-
#[derive(Default)]
241-
/// The `-C link-self-contained` components that can individually be enabled or disabled.
242-
pub struct LinkSelfContainedComponents: u8 {
243-
/// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets)
244-
const CRT_OBJECTS = 1 << 0;
245-
/// libc static library (e.g. on `musl`, `wasi` targets)
246-
const LIBC = 1 << 1;
247-
/// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets)
248-
const UNWIND = 1 << 2;
249-
/// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`)
250-
const LINKER = 1 << 3;
251-
/// Sanitizer runtime libraries
252-
const SANITIZERS = 1 << 4;
253-
/// Other MinGW libs and Windows import libs
254-
const MINGW = 1 << 5;
255-
}
256-
}
257-
258-
impl FromStr for LinkSelfContainedComponents {
259-
type Err = ();
236+
/// The components that are enabled on the CLI, using the `+component` syntax or one of the
237+
/// `true` shorcuts.
238+
enabled_components: LinkSelfContainedComponents,
260239

261-
fn from_str(s: &str) -> Result<Self, Self::Err> {
262-
Ok(match s {
263-
"crto" => LinkSelfContainedComponents::CRT_OBJECTS,
264-
"libc" => LinkSelfContainedComponents::LIBC,
265-
"unwind" => LinkSelfContainedComponents::UNWIND,
266-
"linker" => LinkSelfContainedComponents::LINKER,
267-
"sanitizers" => LinkSelfContainedComponents::SANITIZERS,
268-
"mingw" => LinkSelfContainedComponents::MINGW,
269-
_ => return Err(()),
270-
})
271-
}
240+
/// The components that are disabled on the CLI, using the `-component` syntax or one of the
241+
/// `false` shortcuts.
242+
disabled_components: LinkSelfContainedComponents,
272243
}
273244

274245
impl LinkSelfContained {
275246
/// Incorporates an enabled or disabled component as specified on the CLI, if possible.
276247
/// For example: `+linker`, and `-crto`.
277-
pub(crate) fn handle_cli_component(&mut self, component: &str) -> Result<(), ()> {
248+
pub(crate) fn handle_cli_component(&mut self, component: &str) -> Option<()> {
278249
// Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit
279250
// set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
280251
// set in bulk with its historical values, then manually setting a component clears that
281252
// `explicitly_set` state.
282253
if let Some(component_to_enable) = component.strip_prefix('+') {
283254
self.explicitly_set = None;
284-
self.components.insert(component_to_enable.parse()?);
285-
Ok(())
255+
self.enabled_components
256+
.insert(LinkSelfContainedComponents::from_str(component_to_enable)?);
257+
Some(())
286258
} else if let Some(component_to_disable) = component.strip_prefix('-') {
287259
self.explicitly_set = None;
288-
self.components.remove(component_to_disable.parse()?);
289-
Ok(())
260+
self.disabled_components
261+
.insert(LinkSelfContainedComponents::from_str(component_to_disable)?);
262+
Some(())
290263
} else {
291-
Err(())
264+
None
292265
}
293266
}
294267

295268
/// Turns all components on or off and records that this was done explicitly for compatibility
296269
/// purposes.
297270
pub(crate) fn set_all_explicitly(&mut self, enabled: bool) {
298271
self.explicitly_set = Some(enabled);
299-
self.components = if enabled {
300-
LinkSelfContainedComponents::all()
272+
273+
if enabled {
274+
self.enabled_components = LinkSelfContainedComponents::all();
275+
self.disabled_components = LinkSelfContainedComponents::empty();
301276
} else {
302-
LinkSelfContainedComponents::empty()
303-
};
277+
self.enabled_components = LinkSelfContainedComponents::empty();
278+
self.disabled_components = LinkSelfContainedComponents::all();
279+
}
304280
}
305281

306282
/// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests.
@@ -314,13 +290,32 @@ impl LinkSelfContained {
314290
/// components was set individually. This would also require the `-Zunstable-options` flag, to
315291
/// be allowed.
316292
fn are_unstable_variants_set(&self) -> bool {
317-
let any_component_set = !self.components.is_empty();
293+
let any_component_set =
294+
!self.enabled_components.is_empty() || !self.disabled_components.is_empty();
318295
self.explicitly_set.is_none() && any_component_set
319296
}
320297

321-
/// Returns whether the self-contained linker component is enabled.
322-
pub fn linker(&self) -> bool {
323-
self.components.contains(LinkSelfContainedComponents::LINKER)
298+
/// Returns whether the self-contained linker component was enabled on the CLI, using the
299+
/// `-C link-self-contained=+linker` syntax, or one of the `true` shorcuts.
300+
pub fn is_linker_enabled(&self) -> bool {
301+
self.enabled_components.contains(LinkSelfContainedComponents::LINKER)
302+
}
303+
304+
/// Returns whether the self-contained linker component was disabled on the CLI, using the
305+
/// `-C link-self-contained=-linker` syntax, or one of the `false` shorcuts.
306+
pub fn is_linker_disabled(&self) -> bool {
307+
self.disabled_components.contains(LinkSelfContainedComponents::LINKER)
308+
}
309+
310+
/// Returns CLI inconsistencies to emit errors: individual components were both enabled and
311+
/// disabled.
312+
fn check_consistency(&self) -> Option<LinkSelfContainedComponents> {
313+
if self.explicitly_set.is_some() {
314+
None
315+
} else {
316+
let common = self.enabled_components.intersection(self.disabled_components);
317+
if common.is_empty() { None } else { Some(common) }
318+
}
324319
}
325320
}
326321

@@ -2758,9 +2753,8 @@ pub fn build_session_options(
27582753
}
27592754

27602755
// For testing purposes, until we have more feedback about these options: ensure `-Z
2761-
// unstable-options` is required when using the unstable `-C link-self-contained` options, like
2762-
// `-C link-self-contained=+linker`, and when using the unstable `-C linker-flavor` options, like
2763-
// `-C linker-flavor=gnu-lld-cc`.
2756+
// unstable-options` is required when using the unstable `-C link-self-contained` and `-C
2757+
// linker-flavor` options.
27642758
if !nightly_options::is_unstable_enabled(matches) {
27652759
let uses_unstable_self_contained_option =
27662760
cg.link_self_contained.are_unstable_variants_set();
@@ -2782,6 +2776,19 @@ pub fn build_session_options(
27822776
}
27832777
}
27842778

2779+
// Check `-C link-self-contained` for consistency: individual components cannot be both enabled
2780+
// and disabled at the same time.
2781+
if let Some(erroneous_components) = cg.link_self_contained.check_consistency() {
2782+
let names: String = erroneous_components
2783+
.into_iter()
2784+
.map(|c| c.as_str().unwrap())
2785+
.intersperse(", ")
2786+
.collect();
2787+
handler.early_error(format!(
2788+
"some `-C link-self-contained` components were both enabled and disabled: {names}"
2789+
));
2790+
}
2791+
27852792
let prints = collect_print_requests(handler, &mut cg, &mut unstable_opts, matches);
27862793

27872794
let cg = cg;

compiler/rustc_session/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(option_get_or_insert_default)]
77
#![feature(rustc_attrs)]
88
#![feature(map_many_mut)]
9+
#![feature(iter_intersperse)]
910
#![recursion_limit = "256"]
1011
#![allow(rustc::potential_query_instability)]
1112
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_session/src/options.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ mod parse {
11651165

11661166
// 2. Parse a list of enabled and disabled components.
11671167
for comp in s.split(',') {
1168-
if slot.handle_cli_component(comp).is_err() {
1168+
if slot.handle_cli_component(comp).is_none() {
11691169
return false;
11701170
}
11711171
}

compiler/rustc_target/src/spec/mod.rs

+79-5
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ pub enum LinkerFlavor {
164164

165165
/// Linker flavors available externally through command line (`-Clinker-flavor`)
166166
/// or json target specifications.
167-
/// FIXME: This set has accumulated historically, bring it more in line with the internal
168-
/// linker flavors (`LinkerFlavor`).
167+
/// This set has accumulated historically, and contains both (stable and unstable) legacy values, as
168+
/// well as modern ones matching the internal linker flavors (`LinkerFlavor`).
169169
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
170170
pub enum LinkerFlavorCli {
171-
// New (unstable) flavors, with direct counterparts in `LinkerFlavor`.
171+
// Modern (unstable) flavors, with direct counterparts in `LinkerFlavor`.
172172
Gnu(Cc, Lld),
173173
Darwin(Cc, Lld),
174174
WasmLld(Cc),
@@ -179,7 +179,7 @@ pub enum LinkerFlavorCli {
179179
Bpf,
180180
Ptx,
181181

182-
// Below: the legacy stable values.
182+
// Legacy stable values
183183
Gcc,
184184
Ld,
185185
Lld(LldFlavor),
@@ -504,7 +504,7 @@ linker_flavor_cli_impls! {
504504
(LinkerFlavorCli::Bpf) "bpf"
505505
(LinkerFlavorCli::Ptx) "ptx"
506506

507-
// Below: legacy stable values
507+
// Legacy stable flavors
508508
(LinkerFlavorCli::Gcc) "gcc"
509509
(LinkerFlavorCli::Ld) "ld"
510510
(LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
@@ -520,6 +520,80 @@ impl ToJson for LinkerFlavorCli {
520520
}
521521
}
522522

523+
bitflags::bitflags! {
524+
#[derive(Default)]
525+
/// The `-C link-self-contained` components that can individually be enabled or disabled.
526+
pub struct LinkSelfContainedComponents: u8 {
527+
/// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets)
528+
const CRT_OBJECTS = 1 << 0;
529+
/// libc static library (e.g. on `musl`, `wasi` targets)
530+
const LIBC = 1 << 1;
531+
/// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets)
532+
const UNWIND = 1 << 2;
533+
/// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`)
534+
const LINKER = 1 << 3;
535+
/// Sanitizer runtime libraries
536+
const SANITIZERS = 1 << 4;
537+
/// Other MinGW libs and Windows import libs
538+
const MINGW = 1 << 5;
539+
}
540+
}
541+
542+
impl LinkSelfContainedComponents {
543+
/// Parses a single `-Clink-self-contained` well-known component, not a set of flags.
544+
pub fn from_str(s: &str) -> Option<LinkSelfContainedComponents> {
545+
Some(match s {
546+
"crto" => LinkSelfContainedComponents::CRT_OBJECTS,
547+
"libc" => LinkSelfContainedComponents::LIBC,
548+
"unwind" => LinkSelfContainedComponents::UNWIND,
549+
"linker" => LinkSelfContainedComponents::LINKER,
550+
"sanitizers" => LinkSelfContainedComponents::SANITIZERS,
551+
"mingw" => LinkSelfContainedComponents::MINGW,
552+
_ => return None,
553+
})
554+
}
555+
556+
/// Return the component's name.
557+
///
558+
/// Returns `None` if the bitflags aren't a singular component (but a mix of multiple flags).
559+
pub fn as_str(self) -> Option<&'static str> {
560+
Some(match self {
561+
LinkSelfContainedComponents::CRT_OBJECTS => "crto",
562+
LinkSelfContainedComponents::LIBC => "libc",
563+
LinkSelfContainedComponents::UNWIND => "unwind",
564+
LinkSelfContainedComponents::LINKER => "linker",
565+
LinkSelfContainedComponents::SANITIZERS => "sanitizers",
566+
LinkSelfContainedComponents::MINGW => "mingw",
567+
_ => return None,
568+
})
569+
}
570+
571+
/// Returns an array of all the components.
572+
fn all_components() -> [LinkSelfContainedComponents; 6] {
573+
[
574+
LinkSelfContainedComponents::CRT_OBJECTS,
575+
LinkSelfContainedComponents::LIBC,
576+
LinkSelfContainedComponents::UNWIND,
577+
LinkSelfContainedComponents::LINKER,
578+
LinkSelfContainedComponents::SANITIZERS,
579+
LinkSelfContainedComponents::MINGW,
580+
]
581+
}
582+
}
583+
584+
impl IntoIterator for LinkSelfContainedComponents {
585+
type Item = LinkSelfContainedComponents;
586+
type IntoIter = std::vec::IntoIter<LinkSelfContainedComponents>;
587+
588+
fn into_iter(self) -> Self::IntoIter {
589+
LinkSelfContainedComponents::all_components()
590+
.into_iter()
591+
.filter(|&s| self.contains(s))
592+
.collect::<Vec<_>>()
593+
.into_iter()
594+
}
595+
}
596+
523597
#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
524598
pub enum PanicStrategy {
525599
Unwind,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: some `-C link-self-contained` components were both enabled and disabled: crto, linker
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: some `-C link-self-contained` components were both enabled and disabled: linker
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Checks that self-contained linking components cannot be both enabled and disabled at the same
2+
// time on the CLI.
3+
4+
// check-fail
5+
// revisions: one many
6+
// [one] compile-flags: -Clink-self-contained=-linker -Clink-self-contained=+linker -Zunstable-options
7+
// [many] compile-flags: -Clink-self-contained=+linker,+crto -Clink-self-contained=-linker,-crto -Zunstable-options
8+
// ignore-tidy-linelength
9+
10+
fn main() {}

0 commit comments

Comments
 (0)