Stabilize native library modifier syntax and the whole-archive modifier specifically

This commit is contained in:
Vadim Petrochenkov 2022-02-11 15:08:35 +08:00
parent bb5c437a2c
commit 1004783ef9
33 changed files with 269 additions and 164 deletions

View File

@ -387,13 +387,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if attr.has_name(sym::link) {
for nested_meta in attr.meta_item_list().unwrap_or_default() {
if nested_meta.has_name(sym::modifiers) {
gate_feature_post!(
self,
native_link_modifiers,
nested_meta.span(),
"native link modifiers are experimental"
);
if let Some(modifiers) = nested_meta.value_str() {
for modifier in modifiers.as_str().split(',') {
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
@ -412,7 +405,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_modifier!(
"bundle" => native_link_modifiers_bundle
"verbatim" => native_link_modifiers_verbatim
"whole-archive" => native_link_modifiers_whole_archive
"as-needed" => native_link_modifiers_as_needed
);
}

View File

@ -1844,7 +1844,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// This change is somewhat breaking in practice due to local static libraries being linked
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
if sess.opts.debugging_opts.link_native_libraries {
add_local_native_libraries(cmd, sess, codegen_results);
add_local_native_libraries(cmd, sess, codegen_results, crate_type);
}
// Upstream rust libraries and their nobundle static libraries
@ -2016,6 +2016,16 @@ fn add_order_independent_options(
add_rpath_args(cmd, sess, codegen_results, out_filename);
}
// A dylib may reexport symbols from the linked rlib or native static library.
// Even if some symbol is reexported it's still not necessarily counted as used and may be
// dropped, at least with `ld`-like ELF linkers. So we have to link some rlibs and static
// libraries as whole-archive to avoid losing reexported symbols.
// FIXME: Find a way to mark reexported symbols as used and avoid this use of whole-archive.
fn default_to_whole_archive(sess: &Session, crate_type: CrateType, cmd: &dyn Linker) -> bool {
crate_type == CrateType::Dylib
&& !(sess.target.limit_rdylib_exports && cmd.exported_symbol_means_used_symbol())
}
/// # Native library linking
///
/// User-supplied library search paths (-L on the command line). These are the same paths used to
@ -2029,6 +2039,7 @@ fn add_local_native_libraries(
cmd: &mut dyn Linker,
sess: &Session,
codegen_results: &CodegenResults,
crate_type: CrateType,
) {
let filesearch = sess.target_filesearch(PathKind::All);
for search_path in filesearch.search_paths() {
@ -2046,14 +2057,18 @@ fn add_local_native_libraries(
codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
let search_path = OnceCell::new();
let mut last = (NativeLibKind::Unspecified, None);
let mut last = (None, NativeLibKind::Unspecified, None);
for lib in relevant_libs {
let Some(name) = lib.name else {
continue;
};
// Skip if this library is the same as the last.
last = if (lib.kind, lib.name) == last { continue } else { (lib.kind, lib.name) };
last = if (lib.name, lib.kind, lib.verbatim) == last {
continue;
} else {
(lib.name, lib.kind, lib.verbatim)
};
let verbatim = lib.verbatim.unwrap_or(false);
match lib.kind {
@ -2064,15 +2079,19 @@ fn add_local_native_libraries(
NativeLibKind::Framework { as_needed } => {
cmd.link_framework(name, as_needed.unwrap_or(true))
}
NativeLibKind::Static { bundle: None | Some(true), .. }
| NativeLibKind::Static { whole_archive: Some(true), .. } => {
cmd.link_whole_staticlib(
name,
verbatim,
&search_path.get_or_init(|| archive_search_paths(sess)),
);
NativeLibKind::Static { whole_archive, .. } => {
if whole_archive == Some(true)
|| (whole_archive == None && default_to_whole_archive(sess, crate_type, cmd))
{
cmd.link_whole_staticlib(
name,
verbatim,
&search_path.get_or_init(|| archive_search_paths(sess)),
);
} else {
cmd.link_staticlib(name, verbatim)
}
}
NativeLibKind::Static { .. } => cmd.link_staticlib(name, verbatim),
NativeLibKind::RawDylib => {
// FIXME(#58713): Proper handling for raw dylibs.
bug!("raw_dylib feature not yet implemented");
@ -2197,34 +2216,37 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
// external build system already has the native dependencies defined, and it
// will provide them to the linker itself.
if sess.opts.debugging_opts.link_native_libraries {
let mut last = None;
let mut last = (None, NativeLibKind::Unspecified, None);
for lib in &codegen_results.crate_info.native_libraries[&cnum] {
let Some(name) = lib.name else {
continue;
};
if !relevant_lib(sess, lib) {
// Skip libraries if they are disabled by `#[link(cfg=...)]`
continue;
}
// Skip if this library is the same as the last.
if last == lib.name {
last = if (lib.name, lib.kind, lib.verbatim) == last {
continue;
}
} else {
(lib.name, lib.kind, lib.verbatim)
};
if let Some(static_lib_name) = lib.name {
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
lib.kind
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
lib.kind
{
let verbatim = lib.verbatim.unwrap_or(false);
if whole_archive == Some(true)
|| (whole_archive == None
&& default_to_whole_archive(sess, crate_type, cmd))
{
let verbatim = lib.verbatim.unwrap_or(false);
if whole_archive == Some(true) {
cmd.link_whole_staticlib(
static_lib_name,
verbatim,
search_path.get_or_init(|| archive_search_paths(sess)),
);
} else {
cmd.link_staticlib(static_lib_name, verbatim);
}
last = lib.name;
cmd.link_whole_staticlib(
name,
verbatim,
search_path.get_or_init(|| archive_search_paths(sess)),
);
} else {
cmd.link_staticlib(name, verbatim);
}
}
}
@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
let cratepath = &src.rlib.as_ref().unwrap().0;
let mut link_upstream = |path: &Path| {
// If we're creating a dylib, then we need to include the
// whole of each object in our archive into that artifact. This is
// because a `dylib` can be reused as an intermediate artifact.
//
// Note, though, that we don't want to include the whole of a
// compiler-builtins crate (e.g., compiler-rt) because it'll get
// repeatedly linked anyway.
// We don't want to include the whole compiler-builtins crate (e.g., compiler-rt)
// regardless of the default because it'll get repeatedly linked anyway.
let path = fix_windows_verbatim_for_gcc(path);
if crate_type == CrateType::Dylib
if default_to_whole_archive(sess, crate_type, cmd)
&& codegen_results.crate_info.compiler_builtins != Some(cnum)
{
cmd.link_whole_rlib(&path);
@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries(
sess: &Session,
codegen_results: &CodegenResults,
) {
let mut last = (NativeLibKind::Unspecified, None);
let mut last = (None, NativeLibKind::Unspecified, None);
for &cnum in &codegen_results.crate_info.used_crates {
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
let Some(name) = lib.name else {
@ -2412,7 +2429,11 @@ fn add_upstream_native_libraries(
}
// Skip if this library is the same as the last.
last = if (lib.kind, lib.name) == last { continue } else { (lib.kind, lib.name) };
last = if (lib.name, lib.kind, lib.verbatim) == last {
continue;
} else {
(lib.name, lib.kind, lib.verbatim)
};
let verbatim = lib.verbatim.unwrap_or(false);
match lib.kind {

View File

@ -186,6 +186,9 @@ pub trait Linker {
fn no_crt_objects(&mut self);
fn no_default_libraries(&mut self);
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
fn exported_symbol_means_used_symbol(&self) -> bool {
true
}
fn subsystem(&mut self, subsystem: &str);
fn group_start(&mut self);
fn group_end(&mut self);
@ -724,6 +727,10 @@ impl<'a> Linker for GccLinker<'a> {
}
}
fn exported_symbol_means_used_symbol(&self) -> bool {
self.sess.target.is_like_windows || self.sess.target.is_like_osx
}
fn subsystem(&mut self, subsystem: &str) {
self.linker_arg("--subsystem");
self.linker_arg(&subsystem);
@ -1471,6 +1478,10 @@ impl<'a> Linker for L4Bender<'a> {
return;
}
fn exported_symbol_means_used_symbol(&self) -> bool {
false
}
fn subsystem(&mut self, subsystem: &str) {
self.cmd.arg(&format!("--subsystem {}", subsystem));
}

View File

@ -215,6 +215,10 @@ declare_features! (
/// Allows patterns with concurrent by-move and by-ref bindings.
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
(accepted, native_link_modifiers, "1.61.0", Some(81490), None),
/// Allows specifying the whole-archive link modifier
(accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None),
/// Allows using `#![no_std]`.
(accepted, no_std, "1.6.0", None, None),
/// Allows defining identifiers beyond ASCII.

View File

@ -446,16 +446,12 @@ declare_features! (
(active, must_not_suspend, "1.57.0", Some(83310), None),
/// Allows using `#[naked]` on functions.
(active, naked_functions, "1.9.0", Some(32408), None),
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
(active, native_link_modifiers, "1.53.0", Some(81490), None),
/// Allows specifying the as-needed link modifier
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
/// Allows specifying the bundle link modifier
(active, native_link_modifiers_bundle, "1.53.0", Some(81490), None),
/// Allows specifying the verbatim link modifier
(active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None),
/// Allows specifying the whole-archive link modifier
(active, native_link_modifiers_whole_archive, "1.53.0", Some(81490), None),
/// Allow negative trait implementations.
(active, negative_impls, "1.44.0", Some(68318), None),
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.

View File

@ -1,5 +1,5 @@
#![feature(nll)]
#![feature(native_link_modifiers)]
#![cfg_attr(bootstrap, feature(native_link_modifiers))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
// NOTE: This crate only exists to allow linking on mingw targets.

View File

@ -125,13 +125,18 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
// Do this outside the above loop so we don't depend on modifiers coming
// after kinds
if let Some(item) = items.iter().find(|item| item.has_name(sym::modifiers)) {
let mut modifiers_count = 0;
for item in items.iter().filter(|item| item.has_name(sym::modifiers)) {
if let Some(modifiers) = item.value_str() {
modifiers_count += 1;
let span = item.name_value_literal_span().unwrap();
let mut has_duplicate_modifiers = false;
for modifier in modifiers.as_str().split(',') {
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
// Note: this error also excludes the case with empty modifier
// string, like `modifiers = ""`.
sess.span_err(
span,
"invalid linking modifier syntax, expected '+' or '-' prefix \
@ -143,6 +148,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
match (modifier, &mut lib.kind) {
("bundle", NativeLibKind::Static { bundle, .. }) => {
if bundle.is_some() {
has_duplicate_modifiers = true;
}
*bundle = Some(value);
}
("bundle", _) => {
@ -153,9 +161,17 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
);
}
("verbatim", _) => lib.verbatim = Some(value),
("verbatim", _) => {
if lib.verbatim.is_some() {
has_duplicate_modifiers = true;
}
lib.verbatim = Some(value);
}
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
if whole_archive.is_some() {
has_duplicate_modifiers = true;
}
*whole_archive = Some(value);
}
("whole-archive", _) => {
@ -168,6 +184,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
("as-needed", NativeLibKind::Dylib { as_needed })
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
if as_needed.is_some() {
has_duplicate_modifiers = true;
}
*as_needed = Some(value);
}
("as-needed", _) => {
@ -190,12 +209,22 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
}
}
}
if has_duplicate_modifiers {
let msg =
"same modifier is used multiple times in a single `modifiers` argument";
sess.span_err(item.span(), msg);
}
} else {
let msg = "must be of the form `#[link(modifiers = \"...\")]`";
sess.span_err(item.span(), msg);
}
}
if modifiers_count > 1 {
let msg = "multiple `modifiers` arguments in a single `#[link]` attribute";
sess.span_err(m.span, msg);
}
// In general we require #[link(name = "...")] but we allow
// #[link(wasm_import_module = "...")] without the `name`.
let requires_name = kind_specified || lib.wasm_import_module.is_none();
@ -349,6 +378,15 @@ impl Collector<'_> {
.drain_filter(|lib| {
if let Some(lib_name) = lib.name {
if lib_name.as_str() == passed_lib.name {
// FIXME: This whole logic is questionable, whether modifiers are
// involved or not, library reordering and kind overriding without
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
self.tcx.sess.span_err(
self.tcx.def_span(lib.foreign_module.unwrap()),
"overriding linking modifiers from command line is not supported"
);
}
if passed_lib.kind != NativeLibKind::Unspecified {
lib.kind = passed_lib.kind;
}

View File

@ -1948,9 +1948,6 @@ fn parse_native_lib_kind(
kind: &str,
error_format: ErrorOutputType,
) -> (NativeLibKind, Option<bool>) {
let is_nightly = nightly_options::match_is_nightly_build(matches);
let enable_unstable = nightly_options::is_unstable_enabled(matches);
let (kind, modifiers) = match kind.split_once(':') {
None => (kind, None),
Some((kind, modifiers)) => (kind, Some(modifiers)),
@ -1972,7 +1969,7 @@ fn parse_native_lib_kind(
"linking modifier can't be used with library kind `static-nobundle`",
)
}
if !is_nightly {
if !nightly_options::match_is_nightly_build(matches) {
early_error(
error_format,
"library kind `static-nobundle` are currently unstable and only accepted on \
@ -1988,23 +1985,7 @@ fn parse_native_lib_kind(
};
match modifiers {
None => (kind, None),
Some(modifiers) => {
if !is_nightly {
early_error(
error_format,
"linking modifiers are currently unstable and only accepted on \
the nightly compiler",
);
}
if !enable_unstable {
early_error(
error_format,
"linking modifiers are currently unstable, \
the `-Z unstable-options` flag must also be passed to use it",
)
}
parse_native_lib_modifiers(kind, modifiers, error_format)
}
Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches),
}
}
@ -2012,7 +1993,23 @@ fn parse_native_lib_modifiers(
mut kind: NativeLibKind,
modifiers: &str,
error_format: ErrorOutputType,
matches: &getopts::Matches,
) -> (NativeLibKind, Option<bool>) {
let report_unstable_modifier = |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_error(
error_format,
&format!("{modifier} linking modifier is currently unstable{why}"),
)
}
};
let mut has_duplicate_modifiers = false;
let mut verbatim = None;
for modifier in modifiers.split(',') {
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
@ -2026,6 +2023,10 @@ fn parse_native_lib_modifiers(
match (modifier, &mut kind) {
("bundle", NativeLibKind::Static { bundle, .. }) => {
report_unstable_modifier(modifier);
if bundle.is_some() {
has_duplicate_modifiers = true;
}
*bundle = Some(value);
}
("bundle", _) => early_error(
@ -2034,9 +2035,18 @@ fn parse_native_lib_modifiers(
`static` linking kind",
),
("verbatim", _) => verbatim = Some(value),
("verbatim", _) => {
report_unstable_modifier(modifier);
if verbatim.is_some() {
has_duplicate_modifiers = true;
}
verbatim = Some(value);
}
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
if whole_archive.is_some() {
has_duplicate_modifiers = true;
}
*whole_archive = Some(value);
}
("whole-archive", _) => early_error(
@ -2047,6 +2057,10 @@ fn parse_native_lib_modifiers(
("as-needed", NativeLibKind::Dylib { as_needed })
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
report_unstable_modifier(modifier);
if as_needed.is_some() {
has_duplicate_modifiers = true;
}
*as_needed = Some(value);
}
("as-needed", _) => early_error(
@ -2055,6 +2069,8 @@ fn parse_native_lib_modifiers(
`dylib` and `framework` linking kinds",
),
// Note: this error also excludes the case with empty modifier
// string, like `modifiers = ""`.
_ => early_error(
error_format,
&format!(
@ -2064,6 +2080,9 @@ fn parse_native_lib_modifiers(
),
}
}
if has_duplicate_modifiers {
report_unstable_modifier("duplicating")
}
(kind, verbatim)
}

View File

@ -75,6 +75,12 @@ pub struct NativeLib {
pub dll_imports: Vec<DllImport>,
}
impl NativeLib {
pub fn has_modifiers(&self) -> bool {
self.verbatim.is_some() || self.kind.has_modifiers()
}
}
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
pub struct DllImport {
pub name: Symbol,

View File

@ -43,6 +43,20 @@ pub enum NativeLibKind {
Unspecified,
}
impl NativeLibKind {
pub fn has_modifiers(&self) -> bool {
match self {
NativeLibKind::Static { bundle, whole_archive } => {
bundle.is_some() || whole_archive.is_some()
}
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
as_needed.is_some()
}
NativeLibKind::RawDylib | NativeLibKind::Unspecified => false,
}
}
}
rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
@ -53,6 +67,12 @@ pub struct NativeLib {
pub verbatim: Option<bool>,
}
impl NativeLib {
pub fn has_modifiers(&self) -> bool {
self.verbatim.is_some() || self.kind.has_modifiers()
}
}
rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
/// A path that has been canonicalized along with its original, non-canonicalized form

View File

@ -1,7 +1,7 @@
#![no_std]
#![unstable(feature = "panic_unwind", issue = "32837")]
#![feature(link_cfg)]
#![feature(native_link_modifiers)]
#![cfg_attr(bootstrap, feature(native_link_modifiers))]
#![feature(native_link_modifiers_bundle)]
#![feature(nll)]
#![feature(staged_api)]

View File

@ -37,6 +37,8 @@ KIND=PATH` where `KIND` may be one of:
<a id="option-l-link-lib"></a>
## `-l`: link the generated crate to a native library
Syntax: `-l [KIND[:MODIFIERS]=]NAME[:RENAME]`.
This flag allows you to specify linking to a specific native library when building
a crate.
@ -47,7 +49,13 @@ where `KIND` may be one of:
- `static` A native static library (such as a `.a` archive).
- `framework` A macOS framework.
The kind of library can be specified in a [`#[link]`
If the kind is specified, then linking modifiers can be attached to it.
Modifiers are specified as a comma-delimited string with each modifier prefixed with
either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively.
The last boolean value specified for a given modifier wins. \
Example: `-l static:+whole-archive=mylib`.
The kind of library and the modifiers can also be specified in a [`#[link]`
attribute][link-attribute]. If the kind is not specified in the `link`
attribute or on the command-line, it will link a dynamic library if available,
otherwise it will use a static library. If the kind is specified on the
@ -59,6 +67,22 @@ and `LINK_NAME` is the name of the actual library that will be linked.
[link-attribute]: ../reference/items/external-blocks.html#the-link-attribute
### Linking modifiers: `whole-archive`
This modifier is only compatible with the `static` linking kind.
Using any other kind will result in a compiler error.
`+whole-archive` means that the static library is linked as a whole archive
without throwing any object files away.
This modifier translates to `--whole-archive` for `ld`-like linkers,
to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
The modifier does nothing for linkers that don't support it.
The default for this modifier is `-whole-archive`. \
NOTE: The default may currently be different when building dylibs for some targets,
but it is not guaranteed.
<a id="option-crate-type"></a>
## `--crate-type`: a list of types of crates for the compiler to emit

View File

@ -1,18 +0,0 @@
# `native_link_modifiers_whole_archive`
The tracking issue for this feature is: [#81490]
[#81490]: https://github.com/rust-lang/rust/issues/81490
------------------------
The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier.
Only compatible with the `static` linking kind. Using any other kind will result in a compiler error.
`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away.
This modifier translates to `--whole-archive` for `ld`-like linkers, to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
The modifier does nothing for linkers that don't support it.
The default for this modifier is `-whole-archive`.

View File

@ -1,11 +0,0 @@
# `native_link_modifiers`
The tracking issue for this feature is: [#81490]
[#81490]: https://github.com/rust-lang/rust/issues/81490
------------------------
The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute.
Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. The last boolean value specified for a given modifier wins.

View File

@ -1,6 +1,4 @@
#![feature(native_link_modifiers_bundle)]
#![feature(native_link_modifiers_whole_archive)]
#![feature(native_link_modifiers)]
use std::io::Write;

View File

@ -1,4 +1,4 @@
#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
#![feature(raw_dylib, native_link_modifiers_verbatim)]
#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
extern {

View File

@ -1,5 +0,0 @@
#[link(name = "foo", modifiers = "")]
//~^ ERROR: native link modifiers are experimental
extern "C" {}
fn main() {}

View File

@ -1,12 +0,0 @@
error[E0658]: native link modifiers are experimental
--> $DIR/feature-gate-native_link_modifiers.rs:1:22
|
LL | #[link(name = "foo", modifiers = "")]
| ^^^^^^^^^^^^^^
|
= note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
= help: add `#![feature(native_link_modifiers)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,6 +1,3 @@
#![allow(incomplete_features)]
#![feature(native_link_modifiers)]
#[link(name = "foo", modifiers = "+as-needed")]
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
extern "C" {}

View File

@ -1,5 +1,5 @@
error[E0658]: `#[link(modifiers="as-needed")]` is unstable
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:4:34
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:34
|
LL | #[link(name = "foo", modifiers = "+as-needed")]
| ^^^^^^^^^^^^

View File

@ -1,7 +1,6 @@
// Test native_link_modifiers_bundle don't need static-nobundle
// check-pass
#![feature(native_link_modifiers)]
#![feature(native_link_modifiers_bundle)]
#[link(name = "foo", kind = "static", modifiers = "-bundle")]

View File

@ -1,2 +1,2 @@
error: linking modifiers are currently unstable, the `-Z unstable-options` flag must also be passed to use it
error: bundle linking modifier is currently unstable and only accepted on the nightly compiler

View File

@ -1,6 +1,3 @@
#![allow(incomplete_features)]
#![feature(native_link_modifiers)]
#[link(name = "foo", modifiers = "+bundle")]
//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
extern "C" {}

View File

@ -1,5 +1,5 @@
error[E0658]: `#[link(modifiers="bundle")]` is unstable
--> $DIR/feature-gate-native_link_modifiers_bundle.rs:4:34
--> $DIR/feature-gate-native_link_modifiers_bundle.rs:1:34
|
LL | #[link(name = "foo", modifiers = "+bundle")]
| ^^^^^^^^^

View File

@ -1,6 +1,3 @@
#![allow(incomplete_features)]
#![feature(native_link_modifiers)]
#[link(name = "foo", modifiers = "+verbatim")]
//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
extern "C" {}

View File

@ -1,5 +1,5 @@
error[E0658]: `#[link(modifiers="verbatim")]` is unstable
--> $DIR/feature-gate-native_link_modifiers_verbatim.rs:4:34
--> $DIR/feature-gate-native_link_modifiers_verbatim.rs:1:34
|
LL | #[link(name = "foo", modifiers = "+verbatim")]
| ^^^^^^^^^^^

View File

@ -1,8 +0,0 @@
#![allow(incomplete_features)]
#![feature(native_link_modifiers)]
#[link(name = "foo", modifiers = "+whole-archive")]
//~^ ERROR: `#[link(modifiers="whole-archive")]` is unstable
extern "C" {}
fn main() {}

View File

@ -1,12 +0,0 @@
error[E0658]: `#[link(modifiers="whole-archive")]` is unstable
--> $DIR/feature-gate-native_link_modifiers_whole_archive.rs:4:34
|
LL | #[link(name = "foo", modifiers = "+whole-archive")]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
= help: add `#![feature(native_link_modifiers_whole_archive)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -2,9 +2,7 @@
// build-fail
// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
#![feature(native_link_modifiers)]
#![feature(native_link_modifiers_bundle)]
#![feature(native_link_modifiers_whole_archive)]
#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
extern "C" { }

View File

@ -0,0 +1,3 @@
// compile-flags:-lstatic:+whole-archive,-whole-archive=foo
fn main() {}

View File

@ -0,0 +1,2 @@
error: duplicating linking modifier is currently unstable and only accepted on the nightly compiler

View File

@ -0,0 +1,17 @@
// compile-flags:-ldylib:+as-needed=foo -lstatic=bar -Zunstable-options
#![feature(native_link_modifiers_bundle)]
#[link(name = "foo")]
#[link( //~ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
name = "bar",
kind = "static",
modifiers = "+whole-archive,-whole-archive",
//~^ ERROR same modifier is used multiple times in a single `modifiers` argument
modifiers = "+bundle"
)]
extern "C" {}
//~^ ERROR overriding linking modifiers from command line is not supported
//~| ERROR overriding linking modifiers from command line is not supported
fn main() {}

View File

@ -0,0 +1,32 @@
error: same modifier is used multiple times in a single `modifiers` argument
--> $DIR/modifiers-override.rs:9:5
|
LL | modifiers = "+whole-archive,-whole-archive",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: multiple `modifiers` arguments in a single `#[link]` attribute
--> $DIR/modifiers-override.rs:6:1
|
LL | / #[link(
LL | | name = "bar",
LL | | kind = "static",
LL | | modifiers = "+whole-archive,-whole-archive",
LL | |
LL | | modifiers = "+bundle"
LL | | )]
| |__^
error: overriding linking modifiers from command line is not supported
--> $DIR/modifiers-override.rs:13:1
|
LL | extern "C" {}
| ^^^^^^^^^^^^^
error: overriding linking modifiers from command line is not supported
--> $DIR/modifiers-override.rs:13:1
|
LL | extern "C" {}
| ^^^^^^^^^^^^^
error: aborting due to 4 previous errors