Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed i
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)

attr_parsing_as_needed_compatibility =
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds

attr_parsing_bundle_needs_static =
linking modifier `bundle` is only compatible with `static` linking kind
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
}

(sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed }))
| (sym::as_dash_needed, Some(NativeLibKind::RawDylib { as_needed })) => {
report_unstable_modifier!(native_link_modifiers_as_needed);
assign_modifier(as_needed)
}
Expand Down Expand Up @@ -207,12 +208,12 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {

// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
if !matches!(kind, Some(NativeLibKind::RawDylib { .. })) {
cx.emit_err(ImportNameTypeRaw { span });
}
}

if let Some(NativeLibKind::RawDylib) = kind
if let Some(NativeLibKind::RawDylib { .. }) = kind
&& name.as_str().contains('\0')
{
cx.emit_err(RawDylibNoNul { span: name_span });
Expand Down Expand Up @@ -304,7 +305,7 @@ impl LinkParser {
cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
}

NativeLibKind::RawDylib
NativeLibKind::RawDylib { as_needed: None }
}
sym::link_dash_arg => {
if !features.link_arg_attribute() {
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,7 @@ fn print_native_static_libs(
NativeLibKind::Static { bundle: None | Some(true), .. }
| NativeLibKind::LinkArg
| NativeLibKind::WasmImportModule
| NativeLibKind::RawDylib => None,
| NativeLibKind::RawDylib { .. } => None,
}
})
// deduplication of consecutive repeated libraries, see rust-lang/rust#113209
Expand Down Expand Up @@ -2349,13 +2349,13 @@ fn linker_with_args(
cmd.add_object(&output_path);
}
} else {
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
sess,
codegen_results.crate_info.used_libraries.iter(),
&raw_dylib_dir,
) {
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
cmd.link_dylib_by_name(&link_path, true, false);
cmd.link_dylib_by_name(&link_path, true, as_needed);
}
}
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
Expand Down Expand Up @@ -2396,13 +2396,13 @@ fn linker_with_args(
cmd.add_object(&output_path);
}
} else {
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
sess,
native_libraries_from_nonstatics,
&raw_dylib_dir,
) {
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
cmd.link_dylib_by_name(&link_path, true, false);
cmd.link_dylib_by_name(&link_path, true, as_needed);
}
}

Expand Down Expand Up @@ -2711,7 +2711,7 @@ fn add_native_libs_from_crate(
cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
}
}
NativeLibKind::RawDylib => {
NativeLibKind::RawDylib { as_needed: _ } => {
// Handled separately in `linker_with_args`.
}
NativeLibKind::WasmImportModule => {}
Expand Down
24 changes: 13 additions & 11 deletions compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn collate_raw_dylibs_windows<'a>(
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();

for lib in used_libraries {
if lib.kind == NativeLibKind::RawDylib {
if let NativeLibKind::RawDylib { .. } = lib.kind {
let ext = if lib.verbatim { "" } else { ".dll" };
let name = format!("{}{}", lib.name, ext);
let imports = dylib_table.entry(name.clone()).or_default();
Expand Down Expand Up @@ -128,12 +128,12 @@ pub(super) fn create_raw_dylib_dll_import_libs<'a>(
fn collate_raw_dylibs_elf<'a>(
sess: &Session,
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
) -> Vec<(String, Vec<DllImport>)> {
) -> Vec<(String, Vec<DllImport>, bool)> {
// Use index maps to preserve original order of imports and libraries.
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
let mut dylib_table = FxIndexMap::<String, (FxIndexMap<Symbol, &DllImport>, bool)>::default();

for lib in used_libraries {
if lib.kind == NativeLibKind::RawDylib {
if let NativeLibKind::RawDylib { as_needed } = lib.kind {
let filename = if lib.verbatim {
lib.name.as_str().to_owned()
} else {
Expand All @@ -142,17 +142,19 @@ fn collate_raw_dylibs_elf<'a>(
format!("{prefix}{}{ext}", lib.name)
};

let imports = dylib_table.entry(filename.clone()).or_default();
let (stub_imports, stub_as_needed) =
dylib_table.entry(filename.clone()).or_insert((Default::default(), true));
for import in &lib.dll_imports {
imports.insert(import.name, import);
stub_imports.insert(import.name, import);
}
*stub_as_needed = *stub_as_needed && as_needed.unwrap_or(true);
}
}
sess.dcx().abort_if_errors();
dylib_table
.into_iter()
.map(|(name, imports)| {
(name, imports.into_iter().map(|(_, import)| import.clone()).collect())
.map(|(name, (imports, as_needed))| {
(name, imports.into_iter().map(|(_, import)| import.clone()).collect(), as_needed)
})
.collect()
}
Expand All @@ -161,10 +163,10 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
sess: &Session,
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
raw_dylib_so_dir: &Path,
) -> Vec<String> {
) -> Vec<(String, bool)> {
collate_raw_dylibs_elf(sess, used_libraries)
.into_iter()
.map(|(load_filename, raw_dylib_imports)| {
.map(|(load_filename, raw_dylib_imports, as_needed)| {
use std::hash::Hash;

// `load_filename` is the *target/loader* filename that will end up in NEEDED.
Expand Down Expand Up @@ -205,7 +207,7 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
});
};

temporary_lib_name
(temporary_lib_name, as_needed)
})
.collect()
}
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,10 @@ pub enum NativeLibKind {
},
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
/// On Linux, it refers to a generated shared library stub.
RawDylib,
RawDylib {
/// Whether the dynamic library will be linked only if it satisfies some undefined symbols
as_needed: Option<bool>,
},
/// A macOS-specific kind of dynamic libraries.
Framework {
/// Whether the framework will be linked only if it satisfies some undefined symbols
Expand All @@ -330,11 +333,10 @@ impl NativeLibKind {
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
NativeLibKind::Dylib { as_needed }
| NativeLibKind::Framework { as_needed }
| NativeLibKind::RawDylib { as_needed } => as_needed.is_some(),
NativeLibKind::Unspecified
| NativeLibKind::LinkArg
| NativeLibKind::WasmImportModule => false,
}
Expand All @@ -347,7 +349,9 @@ impl NativeLibKind {
pub fn is_dllimport(&self) -> bool {
matches!(
self,
NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
NativeLibKind::Dylib { .. }
| NativeLibKind::RawDylib { .. }
| NativeLibKind::Unspecified
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ impl<'tcx> Collector<'tcx> {
.flatten()
{
let dll_imports = match attr.kind {
NativeLibKind::RawDylib => foreign_items
NativeLibKind::RawDylib { .. } => foreign_items
.iter()
.map(|&child_item| {
self.build_dll_import(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_session/src/config/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li
),

("as-needed", NativeLibKind::Dylib { as_needed })
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
| ("as-needed", NativeLibKind::Framework { as_needed })
| ("as-needed", NativeLibKind::RawDylib { as_needed }) => {
cx.on_unstable_value(
"linking modifier `as-needed` is unstable",
", the `-Z unstable-options` flag must also be passed to use it",
Expand Down
43 changes: 43 additions & 0 deletions tests/ui/linkage-attr/raw-dylib/elf/as_needed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//@ only-elf
//@ needs-dynamic-linking

//@ only-gnu
//@ only-x86_64
//@ revisions: as_needed no_as_needed no_modifier merge_1 merge_2 merge_3 merge_4

//@ [as_needed] run-pass
//@ [no_as_needed] run-fail
//@ [no_modifier] run-pass
//@ [merge_1] run-fail
//@ [merge_2] run-fail
//@ [merge_3] run-fail
//@ [merge_4] run-pass

#![allow(incomplete_features)]
#![feature(raw_dylib_elf)]
#![feature(native_link_modifiers_as_needed)]

#[cfg_attr(
as_needed,
link(name = "taiqannf1y28z2rw", kind = "raw-dylib", modifiers = "+as-needed")
)]
#[cfg_attr(
no_as_needed,
link(name = "taiqannf1y28z2rw", kind = "raw-dylib", modifiers = "-as-needed")
)]
#[cfg_attr(no_modifier, link(name = "taiqannf1y28z2rw", kind = "raw-dylib"))]
unsafe extern "C" {}

#[cfg_attr(merge_1, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
#[cfg_attr(merge_2, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
#[cfg_attr(merge_3, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
#[cfg_attr(merge_4, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
unsafe extern "C" {}

#[cfg_attr(merge_1, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
#[cfg_attr(merge_2, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
#[cfg_attr(merge_3, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
#[cfg_attr(merge_4, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
unsafe extern "C" {}

fn main() {}
Loading