From 478db489b3074126862cb71cbf924402121f99cb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 11 Nov 2024 21:39:52 +1100 Subject: [PATCH] Move `-l` option parsing into its own submodule No functional change (yet). --- compiler/rustc_session/src/config.rs | 144 +----------------- .../rustc_session/src/config/native_libs.rs | 140 +++++++++++++++++ 2 files changed, 144 insertions(+), 140 deletions(-) create mode 100644 compiler/rustc_session/src/config/native_libs.rs diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 44721bd889a0..61859466a2c8 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -30,17 +30,18 @@ use rustc_target::spec::{ }; use tracing::debug; +pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues}; +use crate::config::native_libs::parse_libs; use crate::errors::FileWriteFail; pub use crate::options::*; use crate::search_paths::SearchPath; -use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; +use crate::utils::CanonicalizedPath; use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; mod cfg; +mod native_libs; pub mod sigpipe; -pub use cfg::{Cfg, CheckCfg, ExpectedValues}; - /// The different settings that the `-C strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { @@ -2134,143 +2135,6 @@ fn parse_assert_incr_state( } } -fn parse_native_lib_kind( - early_dcx: &EarlyDiagCtxt, - matches: &getopts::Matches, - kind: &str, -) -> (NativeLibKind, Option) { - let (kind, modifiers) = match kind.split_once(':') { - None => (kind, None), - Some((kind, modifiers)) => (kind, Some(modifiers)), - }; - - let kind = match kind { - "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, - "dylib" => NativeLibKind::Dylib { as_needed: None }, - "framework" => NativeLibKind::Framework { as_needed: None }, - "link-arg" => { - if !nightly_options::is_unstable_enabled(matches) { - let why = if nightly_options::match_is_nightly_build(matches) { - " and only accepted on the nightly compiler" - } else { - ", the `-Z unstable-options` flag must also be passed to use it" - }; - early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}")) - } - NativeLibKind::LinkArg - } - _ => early_dcx.early_fatal(format!( - "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" - )), - }; - match modifiers { - None => (kind, None), - Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches), - } -} - -fn parse_native_lib_modifiers( - early_dcx: &EarlyDiagCtxt, - mut kind: NativeLibKind, - modifiers: &str, - matches: &getopts::Matches, -) -> (NativeLibKind, Option) { - let mut verbatim = None; - for modifier in modifiers.split(',') { - let (modifier, value) = match modifier.strip_prefix(['+', '-']) { - Some(m) => (m, modifier.starts_with('+')), - None => early_dcx.early_fatal( - "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", - ), - }; - - let report_unstable_modifier = || { - if !nightly_options::is_unstable_enabled(matches) { - let why = if nightly_options::match_is_nightly_build(matches) { - " and only accepted on the nightly compiler" - } else { - ", the `-Z unstable-options` flag must also be passed to use it" - }; - early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}")) - } - }; - let assign_modifier = |dst: &mut Option| { - if dst.is_some() { - let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); - early_dcx.early_fatal(msg) - } else { - *dst = Some(value); - } - }; - match (modifier, &mut kind) { - ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), - ("bundle", _) => early_dcx.early_fatal( - "linking modifier `bundle` is only compatible with `static` linking kind", - ), - - ("verbatim", _) => assign_modifier(&mut verbatim), - - ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { - assign_modifier(whole_archive) - } - ("whole-archive", _) => early_dcx.early_fatal( - "linking modifier `whole-archive` is only compatible with `static` linking kind", - ), - - ("as-needed", NativeLibKind::Dylib { as_needed }) - | ("as-needed", NativeLibKind::Framework { as_needed }) => { - report_unstable_modifier(); - assign_modifier(as_needed) - } - ("as-needed", _) => early_dcx.early_fatal( - "linking modifier `as-needed` is only compatible with \ - `dylib` and `framework` linking kinds", - ), - - // Note: this error also excludes the case with empty modifier - // string, like `modifiers = ""`. - _ => early_dcx.early_fatal(format!( - "unknown linking modifier `{modifier}`, expected one \ - of: bundle, verbatim, whole-archive, as-needed" - )), - } - } - - (kind, verbatim) -} - -fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec { - matches - .opt_strs("l") - .into_iter() - .map(|s| { - // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", - // where KIND is one of "dylib", "framework", "static", "link-arg" and - // where MODIFIERS are a comma separated list of supported modifiers - // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed - // with either + or - to indicate whether it is enabled or disabled. - // The last value specified for a given modifier wins. - let (name, kind, verbatim) = match s.split_once('=') { - None => (s, NativeLibKind::Unspecified, None), - Some((kind, name)) => { - let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind); - (name.to_string(), kind, verbatim) - } - }; - - let (name, new_name) = match name.split_once(':') { - None => (name, None), - Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), - }; - if name.is_empty() { - early_dcx.early_fatal("library name must not be empty"); - } - NativeLib { name, new_name, kind, verbatim } - }) - .collect() -} - pub fn parse_externs( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs new file mode 100644 index 000000000000..288756925f27 --- /dev/null +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -0,0 +1,140 @@ +use crate::EarlyDiagCtxt; +use crate::config::nightly_options; +use crate::utils::{NativeLib, NativeLibKind}; + +pub(crate) fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec { + matches + .opt_strs("l") + .into_iter() + .map(|s| { + // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", + // where KIND is one of "dylib", "framework", "static", "link-arg" and + // where MODIFIERS are a comma separated list of supported modifiers + // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed + // with either + or - to indicate whether it is enabled or disabled. + // The last value specified for a given modifier wins. + let (name, kind, verbatim) = match s.split_once('=') { + None => (s, NativeLibKind::Unspecified, None), + Some((kind, name)) => { + let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind); + (name.to_string(), kind, verbatim) + } + }; + + let (name, new_name) = match name.split_once(':') { + None => (name, None), + Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), + }; + if name.is_empty() { + early_dcx.early_fatal("library name must not be empty"); + } + NativeLib { name, new_name, kind, verbatim } + }) + .collect() +} + +fn parse_native_lib_kind( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, + kind: &str, +) -> (NativeLibKind, Option) { + let (kind, modifiers) = match kind.split_once(':') { + None => (kind, None), + Some((kind, modifiers)) => (kind, Some(modifiers)), + }; + + let kind = match kind { + "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, + "dylib" => NativeLibKind::Dylib { as_needed: None }, + "framework" => NativeLibKind::Framework { as_needed: None }, + "link-arg" => { + if !nightly_options::is_unstable_enabled(matches) { + let why = if nightly_options::match_is_nightly_build(matches) { + " and only accepted on the nightly compiler" + } else { + ", the `-Z unstable-options` flag must also be passed to use it" + }; + early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}")) + } + NativeLibKind::LinkArg + } + _ => early_dcx.early_fatal(format!( + "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" + )), + }; + match modifiers { + None => (kind, None), + Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches), + } +} + +fn parse_native_lib_modifiers( + early_dcx: &EarlyDiagCtxt, + mut kind: NativeLibKind, + modifiers: &str, + matches: &getopts::Matches, +) -> (NativeLibKind, Option) { + let mut verbatim = None; + for modifier in modifiers.split(',') { + let (modifier, value) = match modifier.strip_prefix(['+', '-']) { + Some(m) => (m, modifier.starts_with('+')), + None => early_dcx.early_fatal( + "invalid linking modifier syntax, expected '+' or '-' prefix \ + before one of: bundle, verbatim, whole-archive, as-needed", + ), + }; + + let report_unstable_modifier = || { + if !nightly_options::is_unstable_enabled(matches) { + let why = if nightly_options::match_is_nightly_build(matches) { + " and only accepted on the nightly compiler" + } else { + ", the `-Z unstable-options` flag must also be passed to use it" + }; + early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}")) + } + }; + let assign_modifier = |dst: &mut Option| { + if dst.is_some() { + let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); + early_dcx.early_fatal(msg) + } else { + *dst = Some(value); + } + }; + match (modifier, &mut kind) { + ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), + ("bundle", _) => early_dcx.early_fatal( + "linking modifier `bundle` is only compatible with `static` linking kind", + ), + + ("verbatim", _) => assign_modifier(&mut verbatim), + + ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { + assign_modifier(whole_archive) + } + ("whole-archive", _) => early_dcx.early_fatal( + "linking modifier `whole-archive` is only compatible with `static` linking kind", + ), + + ("as-needed", NativeLibKind::Dylib { as_needed }) + | ("as-needed", NativeLibKind::Framework { as_needed }) => { + report_unstable_modifier(); + assign_modifier(as_needed) + } + ("as-needed", _) => early_dcx.early_fatal( + "linking modifier `as-needed` is only compatible with \ + `dylib` and `framework` linking kinds", + ), + + // Note: this error also excludes the case with empty modifier + // string, like `modifiers = ""`. + _ => early_dcx.early_fatal(format!( + "unknown linking modifier `{modifier}`, expected one \ + of: bundle, verbatim, whole-archive, as-needed" + )), + } + } + + (kind, verbatim) +}