Rollup merge of #132934 - Zalathar:native-libs, r=jieyouxu
Overhaul the `-l` option parser (for linking to native libs) The current parser for `-l` options has accumulated over time, making it hard to follow. This PR tries to clean it up in several ways. Key changes: - This code now gets its own submodule, to slightly reduce clutter in `rustc_session::config`. - Cleaner division between iterating over multiple `-l` options, and processing each individual one. - Separate “split” step that breaks up the value string into `[KIND[:MODIFIERS]=]NAME[:NEW_NAME]`, but leaves parsing/validating those parts to later steps. - This step also gets its own (disposable) unit test, to make sure it works as expected. - A context struct reduces the burden of parameter passing, and makes it easier to write error messages that adapt to nightly/stable compilers. - Fewer calls to `nightly_options` helper functions, because at this point we can get the same information from `UnstableOptions` and `UnstableFeatures` (which are downstream of earlier calls to those helper functions). There should be no overall change in compiler behaviour.
This commit is contained in:
commit
21654a2f44
14 changed files with 286 additions and 148 deletions
|
@ -30,17 +30,18 @@ use rustc_target::spec::{
|
||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues};
|
||||||
|
use crate::config::native_libs::parse_native_libs;
|
||||||
use crate::errors::FileWriteFail;
|
use crate::errors::FileWriteFail;
|
||||||
pub use crate::options::*;
|
pub use crate::options::*;
|
||||||
use crate::search_paths::SearchPath;
|
use crate::search_paths::SearchPath;
|
||||||
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
use crate::utils::CanonicalizedPath;
|
||||||
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
|
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
|
||||||
|
|
||||||
mod cfg;
|
mod cfg;
|
||||||
|
mod native_libs;
|
||||||
pub mod sigpipe;
|
pub mod sigpipe;
|
||||||
|
|
||||||
pub use cfg::{Cfg, CheckCfg, ExpectedValues};
|
|
||||||
|
|
||||||
/// The different settings that the `-C strip` flag can have.
|
/// The different settings that the `-C strip` flag can have.
|
||||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||||
pub enum Strip {
|
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<bool>) {
|
|
||||||
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<bool>) {
|
|
||||||
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<bool>| {
|
|
||||||
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<NativeLib> {
|
|
||||||
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(
|
pub fn parse_externs(
|
||||||
early_dcx: &EarlyDiagCtxt,
|
early_dcx: &EarlyDiagCtxt,
|
||||||
matches: &getopts::Matches,
|
matches: &getopts::Matches,
|
||||||
|
@ -2644,7 +2508,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||||
let debuginfo = select_debuginfo(matches, &cg);
|
let debuginfo = select_debuginfo(matches, &cg);
|
||||||
let debuginfo_compression = unstable_opts.debuginfo_compression;
|
let debuginfo_compression = unstable_opts.debuginfo_compression;
|
||||||
|
|
||||||
let libs = parse_libs(early_dcx, matches);
|
let crate_name = matches.opt_str("crate-name");
|
||||||
|
let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
|
||||||
|
// Parse any `-l` flags, which link to native libraries.
|
||||||
|
let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches);
|
||||||
|
|
||||||
let test = matches.opt_present("test");
|
let test = matches.opt_present("test");
|
||||||
|
|
||||||
|
@ -2659,8 +2526,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||||
|
|
||||||
let externs = parse_externs(early_dcx, matches, &unstable_opts);
|
let externs = parse_externs(early_dcx, matches, &unstable_opts);
|
||||||
|
|
||||||
let crate_name = matches.opt_str("crate-name");
|
|
||||||
|
|
||||||
let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
|
let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
|
||||||
|
|
||||||
let pretty = parse_pretty(early_dcx, &unstable_opts);
|
let pretty = parse_pretty(early_dcx, &unstable_opts);
|
||||||
|
@ -2734,7 +2599,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||||
error_format,
|
error_format,
|
||||||
diagnostic_width,
|
diagnostic_width,
|
||||||
externs,
|
externs,
|
||||||
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
|
unstable_features,
|
||||||
crate_name,
|
crate_name,
|
||||||
libs,
|
libs,
|
||||||
debug_assertions,
|
debug_assertions,
|
||||||
|
|
192
compiler/rustc_session/src/config/native_libs.rs
Normal file
192
compiler/rustc_session/src/config/native_libs.rs
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
//! Parser for the `-l` command-line option, which links the generated crate to
|
||||||
|
//! a native library.
|
||||||
|
//!
|
||||||
|
//! (There is also a similar but separate syntax for `#[link]` attributes,
|
||||||
|
//! which have their own parser in `rustc_metadata`.)
|
||||||
|
|
||||||
|
use rustc_feature::UnstableFeatures;
|
||||||
|
|
||||||
|
use crate::EarlyDiagCtxt;
|
||||||
|
use crate::config::UnstableOptions;
|
||||||
|
use crate::utils::{NativeLib, NativeLibKind};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
/// Parses all `-l` options.
|
||||||
|
pub(crate) fn parse_native_libs(
|
||||||
|
early_dcx: &EarlyDiagCtxt,
|
||||||
|
unstable_opts: &UnstableOptions,
|
||||||
|
unstable_features: UnstableFeatures,
|
||||||
|
matches: &getopts::Matches,
|
||||||
|
) -> Vec<NativeLib> {
|
||||||
|
let cx = ParseNativeLibCx {
|
||||||
|
early_dcx,
|
||||||
|
unstable_options_enabled: unstable_opts.unstable_options,
|
||||||
|
is_nightly: unstable_features.is_nightly_build(),
|
||||||
|
};
|
||||||
|
matches.opt_strs("l").into_iter().map(|value| parse_native_lib(&cx, &value)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ParseNativeLibCx<'a> {
|
||||||
|
early_dcx: &'a EarlyDiagCtxt,
|
||||||
|
unstable_options_enabled: bool,
|
||||||
|
is_nightly: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParseNativeLibCx<'_> {
|
||||||
|
/// If unstable values are not permitted, exits with a fatal error made by
|
||||||
|
/// combining the given strings.
|
||||||
|
fn on_unstable_value(&self, message: &str, if_nightly: &str, if_stable: &str) {
|
||||||
|
if self.unstable_options_enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let suffix = if self.is_nightly { if_nightly } else { if_stable };
|
||||||
|
self.early_dcx.early_fatal(format!("{message}{suffix}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the value of a single `-l` option.
|
||||||
|
fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib {
|
||||||
|
let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value);
|
||||||
|
|
||||||
|
let kind = kind.map_or(NativeLibKind::Unspecified, |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" => {
|
||||||
|
cx.on_unstable_value(
|
||||||
|
"library kind `link-arg` is unstable",
|
||||||
|
", the `-Z unstable-options` flag must also be passed to use it",
|
||||||
|
" and only accepted on the nightly compiler",
|
||||||
|
);
|
||||||
|
NativeLibKind::LinkArg
|
||||||
|
}
|
||||||
|
_ => cx.early_dcx.early_fatal(format!(
|
||||||
|
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Provisionally create the result, so that modifiers can modify it.
|
||||||
|
let mut native_lib = NativeLib {
|
||||||
|
name: name.to_owned(),
|
||||||
|
new_name: new_name.map(str::to_owned),
|
||||||
|
kind,
|
||||||
|
verbatim: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(modifiers) = modifiers {
|
||||||
|
// If multiple modifiers are present, they are separated by commas.
|
||||||
|
for modifier in modifiers.split(',') {
|
||||||
|
parse_and_apply_modifier(cx, modifier, &mut native_lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if native_lib.name.is_empty() {
|
||||||
|
cx.early_dcx.early_fatal("library name must not be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
native_lib
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses one of the comma-separated modifiers (prefixed by `+` or `-`), and
|
||||||
|
/// modifies `native_lib` appropriately.
|
||||||
|
///
|
||||||
|
/// Exits with a fatal error if a malformed/unknown/inappropriate modifier is
|
||||||
|
/// found.
|
||||||
|
fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_lib: &mut NativeLib) {
|
||||||
|
let early_dcx = cx.early_dcx;
|
||||||
|
|
||||||
|
// Split off the leading `+` or `-` into a boolean value.
|
||||||
|
let (modifier, value) = match modifier.split_at_checked(1) {
|
||||||
|
Some(("+", m)) => (m, true),
|
||||||
|
Some(("-", m)) => (m, false),
|
||||||
|
_ => cx.early_dcx.early_fatal(
|
||||||
|
"invalid linking modifier syntax, expected '+' or '-' prefix \
|
||||||
|
before one of: bundle, verbatim, whole-archive, as-needed",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assigns the value (from `+` or `-`) to an empty `Option<bool>`, or emits
|
||||||
|
// a fatal error if the option has already been set.
|
||||||
|
let assign_modifier = |opt_bool: &mut Option<bool>| {
|
||||||
|
if opt_bool.is_some() {
|
||||||
|
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
|
||||||
|
early_dcx.early_fatal(msg)
|
||||||
|
}
|
||||||
|
*opt_bool = Some(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check that the modifier is applicable to the native lib kind, and apply it.
|
||||||
|
match (modifier, &mut native_lib.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 native_lib.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 }) => {
|
||||||
|
cx.on_unstable_value(
|
||||||
|
"linking modifier `as-needed` is unstable",
|
||||||
|
", the `-Z unstable-options` flag must also be passed to use it",
|
||||||
|
" and only accepted on the nightly compiler",
|
||||||
|
);
|
||||||
|
assign_modifier(as_needed)
|
||||||
|
}
|
||||||
|
("as-needed", _) => early_dcx.early_fatal(
|
||||||
|
"linking modifier `as-needed` is only compatible with \
|
||||||
|
`dylib` and `framework` linking kinds",
|
||||||
|
),
|
||||||
|
|
||||||
|
_ => early_dcx.early_fatal(format!(
|
||||||
|
"unknown linking modifier `{modifier}`, expected one \
|
||||||
|
of: bundle, verbatim, whole-archive, as-needed"
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
struct NativeLibParts<'a> {
|
||||||
|
kind: Option<&'a str>,
|
||||||
|
modifiers: Option<&'a str>,
|
||||||
|
name: &'a str,
|
||||||
|
new_name: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Splits a string of the form `[KIND[:MODIFIERS]=]NAME[:NEW_NAME]` into those
|
||||||
|
/// individual parts. This cannot fail, but the resulting strings require
|
||||||
|
/// further validation.
|
||||||
|
fn split_native_lib_value(value: &str) -> NativeLibParts<'_> {
|
||||||
|
// Split the initial value into `[KIND=]NAME`.
|
||||||
|
let name = value;
|
||||||
|
let (kind, name) = match name.split_once('=') {
|
||||||
|
Some((prefix, name)) => (Some(prefix), name),
|
||||||
|
None => (None, name),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Split the kind part, if present, into `KIND[:MODIFIERS]`.
|
||||||
|
let (kind, modifiers) = match kind {
|
||||||
|
Some(kind) => match kind.split_once(':') {
|
||||||
|
Some((kind, modifiers)) => (Some(kind), Some(modifiers)),
|
||||||
|
None => (Some(kind), None),
|
||||||
|
},
|
||||||
|
None => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Split the name part into `NAME[:NEW_NAME]`.
|
||||||
|
let (name, new_name) = match name.split_once(':') {
|
||||||
|
Some((name, new_name)) => (name, Some(new_name)),
|
||||||
|
None => (name, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
NativeLibParts { kind, modifiers, name, new_name }
|
||||||
|
}
|
50
compiler/rustc_session/src/config/native_libs/tests.rs
Normal file
50
compiler/rustc_session/src/config/native_libs/tests.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use crate::config::native_libs::{NativeLibParts, split_native_lib_value};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split() {
|
||||||
|
// This is a unit test for some implementation details, so consider deleting
|
||||||
|
// it if it gets in the way.
|
||||||
|
use NativeLibParts as P;
|
||||||
|
|
||||||
|
let examples = &[
|
||||||
|
("", P { kind: None, modifiers: None, name: "", new_name: None }),
|
||||||
|
("foo", P { kind: None, modifiers: None, name: "foo", new_name: None }),
|
||||||
|
("foo:", P { kind: None, modifiers: None, name: "foo", new_name: Some("") }),
|
||||||
|
("foo:bar", P { kind: None, modifiers: None, name: "foo", new_name: Some("bar") }),
|
||||||
|
(":bar", P { kind: None, modifiers: None, name: "", new_name: Some("bar") }),
|
||||||
|
("kind=foo", P { kind: Some("kind"), modifiers: None, name: "foo", new_name: None }),
|
||||||
|
(":mods=foo", P { kind: Some(""), modifiers: Some("mods"), name: "foo", new_name: None }),
|
||||||
|
(":mods=:bar", P {
|
||||||
|
kind: Some(""),
|
||||||
|
modifiers: Some("mods"),
|
||||||
|
name: "",
|
||||||
|
new_name: Some("bar"),
|
||||||
|
}),
|
||||||
|
("kind=foo:bar", P {
|
||||||
|
kind: Some("kind"),
|
||||||
|
modifiers: None,
|
||||||
|
name: "foo",
|
||||||
|
new_name: Some("bar"),
|
||||||
|
}),
|
||||||
|
("kind:mods=foo", P {
|
||||||
|
kind: Some("kind"),
|
||||||
|
modifiers: Some("mods"),
|
||||||
|
name: "foo",
|
||||||
|
new_name: None,
|
||||||
|
}),
|
||||||
|
("kind:mods=foo:bar", P {
|
||||||
|
kind: Some("kind"),
|
||||||
|
modifiers: Some("mods"),
|
||||||
|
name: "foo",
|
||||||
|
new_name: Some("bar"),
|
||||||
|
}),
|
||||||
|
("::==::", P { kind: Some(""), modifiers: Some(":"), name: "=", new_name: Some(":") }),
|
||||||
|
("==::==", P { kind: Some(""), modifiers: None, name: "=", new_name: Some(":==") }),
|
||||||
|
];
|
||||||
|
|
||||||
|
for &(value, ref expected) in examples {
|
||||||
|
println!("{value:?}");
|
||||||
|
let actual = split_native_lib_value(value);
|
||||||
|
assert_eq!(&actual, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0658]: link kind `link-arg` is unstable
|
error[E0658]: link kind `link-arg` is unstable
|
||||||
--> $DIR/feature-gate-link-arg-attribute.rs:1:15
|
--> $DIR/feature-gate-link-arg-attribute.rs:5:15
|
||||||
|
|
|
|
||||||
LL | #[link(kind = "link-arg", name = "foo")]
|
LL | #[link(kind = "link-arg", name = "foo")]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: unknown linking modifier `link-arg`, expected one of: bundle, verbatim, whole-archive, as-needed
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
//@ revisions: in_attr in_flag
|
||||||
|
//@[in_flag] compile-flags: -l dylib:+link-arg=foo
|
||||||
|
|
||||||
|
#[cfg(in_attr)]
|
||||||
#[link(kind = "link-arg", name = "foo")]
|
#[link(kind = "link-arg", name = "foo")]
|
||||||
//~^ ERROR link kind `link-arg` is unstable
|
//[in_attr]~^ ERROR link kind `link-arg` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0658]: linking modifier `as-needed` is unstable
|
error[E0658]: linking modifier `as-needed` is unstable
|
||||||
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50
|
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:5:50
|
||||||
|
|
|
|
||||||
LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
|
LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: linking modifier `as-needed` is unstable, the `-Z unstable-options` flag must also be passed to use it
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
//@ revisions: in_attr in_flag
|
||||||
|
//@[in_flag] compile-flags: -l dylib:+as-needed=foo
|
||||||
|
|
||||||
|
#[cfg(in_attr)]
|
||||||
#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
|
#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
|
||||||
//~^ ERROR: linking modifier `as-needed` is unstable
|
//[in_attr]~^ ERROR: linking modifier `as-needed` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: unknown linking modifier ``, expected one of: bundle, verbatim, whole-archive, as-needed
|
||||||
|
|
11
tests/ui/native-library-link-flags/modifiers-bad.rs
Normal file
11
tests/ui/native-library-link-flags/modifiers-bad.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//@ edition: 2021
|
||||||
|
//@ revisions: blank no-prefix prefix-only unknown
|
||||||
|
|
||||||
|
//@[blank] compile-flags: -l static:=foo
|
||||||
|
//@[no-prefix] compile-flags: -l static:bundle=foo
|
||||||
|
//@[prefix-only] compile-flags: -l static:+=foo
|
||||||
|
//@[unknown] compile-flags: -l static:+ferris=foo
|
||||||
|
|
||||||
|
// Tests various illegal values for the "modifier" part of an `-l` flag.
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: unknown linking modifier `ferris`, expected one of: bundle, verbatim, whole-archive, as-needed
|
||||||
|
|
Loading…
Add table
Reference in a new issue