mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Rollup merge of #93901 - petrochenkov:linkmod, r=wesleywiser
Stabilize native library modifier syntax and the `whole-archive` modifier specifically Stabilization report: https://github.com/rust-lang/rust/pull/93901#issuecomment-1041325522 cc https://github.com/rust-lang/rust/issues/81490
This commit is contained in:
commit
b75f384d0b
@ -387,13 +387,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
if attr.has_name(sym::link) {
|
if attr.has_name(sym::link) {
|
||||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||||
if nested_meta.has_name(sym::modifiers) {
|
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() {
|
if let Some(modifiers) = nested_meta.value_str() {
|
||||||
for modifier in modifiers.as_str().split(',') {
|
for modifier in modifiers.as_str().split(',') {
|
||||||
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
|
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
|
||||||
@ -412,7 +405,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
gate_modifier!(
|
gate_modifier!(
|
||||||
"bundle" => native_link_modifiers_bundle
|
"bundle" => native_link_modifiers_bundle
|
||||||
"verbatim" => native_link_modifiers_verbatim
|
"verbatim" => native_link_modifiers_verbatim
|
||||||
"whole-archive" => native_link_modifiers_whole_archive
|
|
||||||
"as-needed" => native_link_modifiers_as_needed
|
"as-needed" => native_link_modifiers_as_needed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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
|
// 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.
|
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
|
||||||
if sess.opts.debugging_opts.link_native_libraries {
|
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
|
// 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);
|
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
|
/// # Native library linking
|
||||||
///
|
///
|
||||||
/// User-supplied library search paths (-L on the command line). These are the same paths used to
|
/// 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,
|
cmd: &mut dyn Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
|
crate_type: CrateType,
|
||||||
) {
|
) {
|
||||||
let filesearch = sess.target_filesearch(PathKind::All);
|
let filesearch = sess.target_filesearch(PathKind::All);
|
||||||
for search_path in filesearch.search_paths() {
|
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));
|
codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
|
||||||
|
|
||||||
let search_path = OnceCell::new();
|
let search_path = OnceCell::new();
|
||||||
let mut last = (NativeLibKind::Unspecified, None);
|
let mut last = (None, NativeLibKind::Unspecified, None);
|
||||||
for lib in relevant_libs {
|
for lib in relevant_libs {
|
||||||
let Some(name) = lib.name else {
|
let Some(name) = lib.name else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip if this library is the same as the last.
|
// 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);
|
let verbatim = lib.verbatim.unwrap_or(false);
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
@ -2064,15 +2079,19 @@ fn add_local_native_libraries(
|
|||||||
NativeLibKind::Framework { as_needed } => {
|
NativeLibKind::Framework { as_needed } => {
|
||||||
cmd.link_framework(name, as_needed.unwrap_or(true))
|
cmd.link_framework(name, as_needed.unwrap_or(true))
|
||||||
}
|
}
|
||||||
NativeLibKind::Static { bundle: None | Some(true), .. }
|
NativeLibKind::Static { whole_archive, .. } => {
|
||||||
| NativeLibKind::Static { whole_archive: Some(true), .. } => {
|
if whole_archive == Some(true)
|
||||||
cmd.link_whole_staticlib(
|
|| (whole_archive == None && default_to_whole_archive(sess, crate_type, cmd))
|
||||||
name,
|
{
|
||||||
verbatim,
|
cmd.link_whole_staticlib(
|
||||||
&search_path.get_or_init(|| archive_search_paths(sess)),
|
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 => {
|
NativeLibKind::RawDylib => {
|
||||||
// FIXME(#58713): Proper handling for raw dylibs.
|
// FIXME(#58713): Proper handling for raw dylibs.
|
||||||
bug!("raw_dylib feature not yet implemented");
|
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
|
// external build system already has the native dependencies defined, and it
|
||||||
// will provide them to the linker itself.
|
// will provide them to the linker itself.
|
||||||
if sess.opts.debugging_opts.link_native_libraries {
|
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] {
|
for lib in &codegen_results.crate_info.native_libraries[&cnum] {
|
||||||
|
let Some(name) = lib.name else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if !relevant_lib(sess, lib) {
|
if !relevant_lib(sess, lib) {
|
||||||
// Skip libraries if they are disabled by `#[link(cfg=...)]`
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if this library is the same as the last.
|
// Skip if this library is the same as the last.
|
||||||
if last == lib.name {
|
last = if (lib.name, lib.kind, lib.verbatim) == last {
|
||||||
continue;
|
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 } =
|
||||||
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
|
lib.kind
|
||||||
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);
|
cmd.link_whole_staticlib(
|
||||||
if whole_archive == Some(true) {
|
name,
|
||||||
cmd.link_whole_staticlib(
|
verbatim,
|
||||||
static_lib_name,
|
search_path.get_or_init(|| archive_search_paths(sess)),
|
||||||
verbatim,
|
);
|
||||||
search_path.get_or_init(|| archive_search_paths(sess)),
|
} else {
|
||||||
);
|
cmd.link_staticlib(name, verbatim);
|
||||||
} else {
|
|
||||||
cmd.link_staticlib(static_lib_name, verbatim);
|
|
||||||
}
|
|
||||||
|
|
||||||
last = lib.name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||||
|
|
||||||
let mut link_upstream = |path: &Path| {
|
let mut link_upstream = |path: &Path| {
|
||||||
// If we're creating a dylib, then we need to include the
|
// We don't want to include the whole compiler-builtins crate (e.g., compiler-rt)
|
||||||
// whole of each object in our archive into that artifact. This is
|
// regardless of the default because it'll get repeatedly linked anyway.
|
||||||
// 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.
|
|
||||||
let path = fix_windows_verbatim_for_gcc(path);
|
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)
|
&& codegen_results.crate_info.compiler_builtins != Some(cnum)
|
||||||
{
|
{
|
||||||
cmd.link_whole_rlib(&path);
|
cmd.link_whole_rlib(&path);
|
||||||
@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries(
|
|||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: &CodegenResults,
|
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 &cnum in &codegen_results.crate_info.used_crates {
|
||||||
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
|
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
|
||||||
let Some(name) = lib.name else {
|
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.
|
// 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);
|
let verbatim = lib.verbatim.unwrap_or(false);
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
|
@ -186,6 +186,9 @@ pub trait Linker {
|
|||||||
fn no_crt_objects(&mut self);
|
fn no_crt_objects(&mut self);
|
||||||
fn no_default_libraries(&mut self);
|
fn no_default_libraries(&mut self);
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
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 subsystem(&mut self, subsystem: &str);
|
||||||
fn group_start(&mut self);
|
fn group_start(&mut self);
|
||||||
fn group_end(&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) {
|
fn subsystem(&mut self, subsystem: &str) {
|
||||||
self.linker_arg("--subsystem");
|
self.linker_arg("--subsystem");
|
||||||
self.linker_arg(&subsystem);
|
self.linker_arg(&subsystem);
|
||||||
@ -1471,6 +1478,10 @@ impl<'a> Linker for L4Bender<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exported_symbol_means_used_symbol(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn subsystem(&mut self, subsystem: &str) {
|
fn subsystem(&mut self, subsystem: &str) {
|
||||||
self.cmd.arg(&format!("--subsystem {}", subsystem));
|
self.cmd.arg(&format!("--subsystem {}", subsystem));
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,10 @@ declare_features! (
|
|||||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
/// 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.
|
/// 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),
|
(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]`.
|
/// Allows using `#![no_std]`.
|
||||||
(accepted, no_std, "1.6.0", None, None),
|
(accepted, no_std, "1.6.0", None, None),
|
||||||
/// Allows defining identifiers beyond ASCII.
|
/// Allows defining identifiers beyond ASCII.
|
||||||
|
@ -446,16 +446,12 @@ declare_features! (
|
|||||||
(active, must_not_suspend, "1.57.0", Some(83310), None),
|
(active, must_not_suspend, "1.57.0", Some(83310), None),
|
||||||
/// Allows using `#[naked]` on functions.
|
/// Allows using `#[naked]` on functions.
|
||||||
(active, naked_functions, "1.9.0", Some(32408), None),
|
(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
|
/// Allows specifying the as-needed link modifier
|
||||||
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
||||||
/// Allows specifying the bundle link modifier
|
/// Allows specifying the bundle link modifier
|
||||||
(active, native_link_modifiers_bundle, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_bundle, "1.53.0", Some(81490), None),
|
||||||
/// Allows specifying the verbatim link modifier
|
/// Allows specifying the verbatim link modifier
|
||||||
(active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None),
|
(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.
|
/// Allow negative trait implementations.
|
||||||
(active, negative_impls, "1.44.0", Some(68318), None),
|
(active, negative_impls, "1.44.0", Some(68318), None),
|
||||||
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
|
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![feature(nll)]
|
#![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/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
|
|
||||||
// NOTE: This crate only exists to allow linking on mingw targets.
|
// NOTE: This crate only exists to allow linking on mingw targets.
|
||||||
|
@ -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
|
// Do this outside the above loop so we don't depend on modifiers coming
|
||||||
// after kinds
|
// 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() {
|
if let Some(modifiers) = item.value_str() {
|
||||||
|
modifiers_count += 1;
|
||||||
let span = item.name_value_literal_span().unwrap();
|
let span = item.name_value_literal_span().unwrap();
|
||||||
|
let mut has_duplicate_modifiers = false;
|
||||||
for modifier in modifiers.as_str().split(',') {
|
for modifier in modifiers.as_str().split(',') {
|
||||||
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
||||||
Some(m) => (m, modifier.starts_with('+')),
|
Some(m) => (m, modifier.starts_with('+')),
|
||||||
None => {
|
None => {
|
||||||
|
// Note: this error also excludes the case with empty modifier
|
||||||
|
// string, like `modifiers = ""`.
|
||||||
sess.span_err(
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
"invalid linking modifier syntax, expected '+' or '-' prefix \
|
"invalid linking modifier syntax, expected '+' or '-' prefix \
|
||||||
@ -143,6 +148,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
|
|
||||||
match (modifier, &mut lib.kind) {
|
match (modifier, &mut lib.kind) {
|
||||||
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
||||||
|
if bundle.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*bundle = Some(value);
|
*bundle = Some(value);
|
||||||
}
|
}
|
||||||
("bundle", _) => {
|
("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, .. }) => {
|
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
||||||
|
if whole_archive.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*whole_archive = Some(value);
|
*whole_archive = Some(value);
|
||||||
}
|
}
|
||||||
("whole-archive", _) => {
|
("whole-archive", _) => {
|
||||||
@ -168,6 +184,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
|||||||
|
|
||||||
("as-needed", NativeLibKind::Dylib { as_needed })
|
("as-needed", NativeLibKind::Dylib { as_needed })
|
||||||
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
||||||
|
if as_needed.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*as_needed = Some(value);
|
*as_needed = Some(value);
|
||||||
}
|
}
|
||||||
("as-needed", _) => {
|
("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 {
|
} else {
|
||||||
let msg = "must be of the form `#[link(modifiers = \"...\")]`";
|
let msg = "must be of the form `#[link(modifiers = \"...\")]`";
|
||||||
sess.span_err(item.span(), msg);
|
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
|
// In general we require #[link(name = "...")] but we allow
|
||||||
// #[link(wasm_import_module = "...")] without the `name`.
|
// #[link(wasm_import_module = "...")] without the `name`.
|
||||||
let requires_name = kind_specified || lib.wasm_import_module.is_none();
|
let requires_name = kind_specified || lib.wasm_import_module.is_none();
|
||||||
@ -349,6 +378,15 @@ impl Collector<'_> {
|
|||||||
.drain_filter(|lib| {
|
.drain_filter(|lib| {
|
||||||
if let Some(lib_name) = lib.name {
|
if let Some(lib_name) = lib.name {
|
||||||
if lib_name.as_str() == passed_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 {
|
if passed_lib.kind != NativeLibKind::Unspecified {
|
||||||
lib.kind = passed_lib.kind;
|
lib.kind = passed_lib.kind;
|
||||||
}
|
}
|
||||||
|
@ -1948,9 +1948,6 @@ fn parse_native_lib_kind(
|
|||||||
kind: &str,
|
kind: &str,
|
||||||
error_format: ErrorOutputType,
|
error_format: ErrorOutputType,
|
||||||
) -> (NativeLibKind, Option<bool>) {
|
) -> (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(':') {
|
let (kind, modifiers) = match kind.split_once(':') {
|
||||||
None => (kind, None),
|
None => (kind, None),
|
||||||
Some((kind, modifiers)) => (kind, Some(modifiers)),
|
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`",
|
"linking modifier can't be used with library kind `static-nobundle`",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if !is_nightly {
|
if !nightly_options::match_is_nightly_build(matches) {
|
||||||
early_error(
|
early_error(
|
||||||
error_format,
|
error_format,
|
||||||
"library kind `static-nobundle` are currently unstable and only accepted on \
|
"library kind `static-nobundle` are currently unstable and only accepted on \
|
||||||
@ -1988,23 +1985,7 @@ fn parse_native_lib_kind(
|
|||||||
};
|
};
|
||||||
match modifiers {
|
match modifiers {
|
||||||
None => (kind, None),
|
None => (kind, None),
|
||||||
Some(modifiers) => {
|
Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches),
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2012,7 +1993,23 @@ fn parse_native_lib_modifiers(
|
|||||||
mut kind: NativeLibKind,
|
mut kind: NativeLibKind,
|
||||||
modifiers: &str,
|
modifiers: &str,
|
||||||
error_format: ErrorOutputType,
|
error_format: ErrorOutputType,
|
||||||
|
matches: &getopts::Matches,
|
||||||
) -> (NativeLibKind, Option<bool>) {
|
) -> (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;
|
let mut verbatim = None;
|
||||||
for modifier in modifiers.split(',') {
|
for modifier in modifiers.split(',') {
|
||||||
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
||||||
@ -2026,6 +2023,10 @@ fn parse_native_lib_modifiers(
|
|||||||
|
|
||||||
match (modifier, &mut kind) {
|
match (modifier, &mut kind) {
|
||||||
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
||||||
|
report_unstable_modifier(modifier);
|
||||||
|
if bundle.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*bundle = Some(value);
|
*bundle = Some(value);
|
||||||
}
|
}
|
||||||
("bundle", _) => early_error(
|
("bundle", _) => early_error(
|
||||||
@ -2034,9 +2035,18 @@ fn parse_native_lib_modifiers(
|
|||||||
`static` linking kind",
|
`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, .. }) => {
|
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
||||||
|
if whole_archive.is_some() {
|
||||||
|
has_duplicate_modifiers = true;
|
||||||
|
}
|
||||||
*whole_archive = Some(value);
|
*whole_archive = Some(value);
|
||||||
}
|
}
|
||||||
("whole-archive", _) => early_error(
|
("whole-archive", _) => early_error(
|
||||||
@ -2047,6 +2057,10 @@ fn parse_native_lib_modifiers(
|
|||||||
|
|
||||||
("as-needed", NativeLibKind::Dylib { as_needed })
|
("as-needed", NativeLibKind::Dylib { as_needed })
|
||||||
| ("as-needed", NativeLibKind::Framework { 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 = Some(value);
|
||||||
}
|
}
|
||||||
("as-needed", _) => early_error(
|
("as-needed", _) => early_error(
|
||||||
@ -2055,6 +2069,8 @@ fn parse_native_lib_modifiers(
|
|||||||
`dylib` and `framework` linking kinds",
|
`dylib` and `framework` linking kinds",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Note: this error also excludes the case with empty modifier
|
||||||
|
// string, like `modifiers = ""`.
|
||||||
_ => early_error(
|
_ => early_error(
|
||||||
error_format,
|
error_format,
|
||||||
&format!(
|
&format!(
|
||||||
@ -2064,6 +2080,9 @@ fn parse_native_lib_modifiers(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if has_duplicate_modifiers {
|
||||||
|
report_unstable_modifier("duplicating")
|
||||||
|
}
|
||||||
|
|
||||||
(kind, verbatim)
|
(kind, verbatim)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,12 @@ pub struct NativeLib {
|
|||||||
pub dll_imports: Vec<DllImport>,
|
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)]
|
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||||
pub struct DllImport {
|
pub struct DllImport {
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
|
@ -43,6 +43,20 @@ pub enum NativeLibKind {
|
|||||||
Unspecified,
|
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);
|
rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
|
||||||
@ -53,6 +67,12 @@ pub struct NativeLib {
|
|||||||
pub verbatim: Option<bool>,
|
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);
|
rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
|
||||||
|
|
||||||
/// A path that has been canonicalized along with its original, non-canonicalized form
|
/// A path that has been canonicalized along with its original, non-canonicalized form
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![unstable(feature = "panic_unwind", issue = "32837")]
|
#![unstable(feature = "panic_unwind", issue = "32837")]
|
||||||
#![feature(link_cfg)]
|
#![feature(link_cfg)]
|
||||||
#![feature(native_link_modifiers)]
|
#![cfg_attr(bootstrap, feature(native_link_modifiers))]
|
||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
|
@ -37,6 +37,8 @@ KIND=PATH` where `KIND` may be one of:
|
|||||||
<a id="option-l-link-lib"></a>
|
<a id="option-l-link-lib"></a>
|
||||||
## `-l`: link the generated crate to a native library
|
## `-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
|
This flag allows you to specify linking to a specific native library when building
|
||||||
a crate.
|
a crate.
|
||||||
|
|
||||||
@ -47,7 +49,13 @@ where `KIND` may be one of:
|
|||||||
- `static` — A native static library (such as a `.a` archive).
|
- `static` — A native static library (such as a `.a` archive).
|
||||||
- `framework` — A macOS framework.
|
- `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][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,
|
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
|
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
|
[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>
|
<a id="option-crate-type"></a>
|
||||||
## `--crate-type`: a list of types of crates for the compiler to emit
|
## `--crate-type`: a list of types of crates for the compiler to emit
|
||||||
|
|
||||||
|
@ -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`.
|
|
@ -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.
|
|
@ -1,6 +1,4 @@
|
|||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
#![feature(native_link_modifiers_whole_archive)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
@ -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")]
|
#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
|
||||||
extern {
|
extern {
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#[link(name = "foo", modifiers = "")]
|
|
||||||
//~^ ERROR: native link modifiers are experimental
|
|
||||||
extern "C" {}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -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`.
|
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+as-needed")]
|
#[link(name = "foo", modifiers = "+as-needed")]
|
||||||
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
|
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="as-needed")]` is unstable
|
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")]
|
LL | #[link(name = "foo", modifiers = "+as-needed")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Test native_link_modifiers_bundle don't need static-nobundle
|
// Test native_link_modifiers_bundle don't need static-nobundle
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
#![feature(native_link_modifiers_bundle)]
|
#![feature(native_link_modifiers_bundle)]
|
||||||
|
|
||||||
#[link(name = "foo", kind = "static", modifiers = "-bundle")]
|
#[link(name = "foo", kind = "static", modifiers = "-bundle")]
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+bundle")]
|
#[link(name = "foo", modifiers = "+bundle")]
|
||||||
//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
|
//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="bundle")]` is unstable
|
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")]
|
LL | #[link(name = "foo", modifiers = "+bundle")]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(native_link_modifiers)]
|
|
||||||
|
|
||||||
#[link(name = "foo", modifiers = "+verbatim")]
|
#[link(name = "foo", modifiers = "+verbatim")]
|
||||||
//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
|
//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0658]: `#[link(modifiers="verbatim")]` is unstable
|
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")]
|
LL | #[link(name = "foo", modifiers = "+verbatim")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -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() {}
|
|
@ -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`.
|
|
@ -2,9 +2,7 @@
|
|||||||
// build-fail
|
// build-fail
|
||||||
// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
|
// 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_bundle)]
|
||||||
#![feature(native_link_modifiers_whole_archive)]
|
|
||||||
|
|
||||||
#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
|
#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
|
||||||
extern "C" { }
|
extern "C" { }
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
// compile-flags:-lstatic:+whole-archive,-whole-archive=foo
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,2 @@
|
|||||||
|
error: duplicating linking modifier is currently unstable and only accepted on the nightly compiler
|
||||||
|
|
17
src/test/ui/native-library-link-flags/modifiers-override.rs
Normal file
17
src/test/ui/native-library-link-flags/modifiers-override.rs
Normal 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() {}
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user