Skip to content

Commit f672671

Browse files
committed
support link modifier as-needed for raw-dylib-elf
1 parent b53c72f commit f672671

File tree

8 files changed

+82
-31
lines changed

8 files changed

+82
-31
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed i
197197
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
198198
199199
attr_parsing_as_needed_compatibility =
200-
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
200+
linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds
201201
202202
attr_parsing_bundle_needs_static =
203203
linking modifier `bundle` is only compatible with `static` linking kind

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
168168
}
169169

170170
(sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
171-
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
171+
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed }))
172+
| (sym::as_dash_needed, Some(NativeLibKind::RawDylib { as_needed })) => {
172173
report_unstable_modifier!(native_link_modifiers_as_needed);
173174
assign_modifier(as_needed)
174175
}
@@ -207,12 +208,12 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
207208

208209
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
209210
if let Some((_, span)) = import_name_type {
210-
if kind != Some(NativeLibKind::RawDylib) {
211+
if !matches!(kind, Some(NativeLibKind::RawDylib { .. })) {
211212
cx.emit_err(ImportNameTypeRaw { span });
212213
}
213214
}
214215

215-
if let Some(NativeLibKind::RawDylib) = kind
216+
if let Some(NativeLibKind::RawDylib { .. }) = kind
216217
&& name.as_str().contains('\0')
217218
{
218219
cx.emit_err(RawDylibNoNul { span: name_span });
@@ -304,7 +305,7 @@ impl LinkParser {
304305
cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
305306
}
306307

307-
NativeLibKind::RawDylib
308+
NativeLibKind::RawDylib { as_needed: None }
308309
}
309310
sym::link_dash_arg => {
310311
if !features.link_arg_attribute() {

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ fn print_native_static_libs(
14851485
NativeLibKind::Static { bundle: None | Some(true), .. }
14861486
| NativeLibKind::LinkArg
14871487
| NativeLibKind::WasmImportModule
1488-
| NativeLibKind::RawDylib => None,
1488+
| NativeLibKind::RawDylib { .. } => None,
14891489
}
14901490
})
14911491
// deduplication of consecutive repeated libraries, see rust-lang/rust#113209
@@ -2349,13 +2349,13 @@ fn linker_with_args(
23492349
cmd.add_object(&output_path);
23502350
}
23512351
} else {
2352-
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2352+
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
23532353
sess,
23542354
codegen_results.crate_info.used_libraries.iter(),
23552355
&raw_dylib_dir,
23562356
) {
23572357
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2358-
cmd.link_dylib_by_name(&link_path, true, false);
2358+
cmd.link_dylib_by_name(&link_path, true, as_needed);
23592359
}
23602360
}
23612361
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
@@ -2396,13 +2396,13 @@ fn linker_with_args(
23962396
cmd.add_object(&output_path);
23972397
}
23982398
} else {
2399-
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2399+
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
24002400
sess,
24012401
native_libraries_from_nonstatics,
24022402
&raw_dylib_dir,
24032403
) {
24042404
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2405-
cmd.link_dylib_by_name(&link_path, true, false);
2405+
cmd.link_dylib_by_name(&link_path, true, as_needed);
24062406
}
24072407
}
24082408

@@ -2711,7 +2711,7 @@ fn add_native_libs_from_crate(
27112711
cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
27122712
}
27132713
}
2714-
NativeLibKind::RawDylib => {
2714+
NativeLibKind::RawDylib { as_needed: _ } => {
27152715
// Handled separately in `linker_with_args`.
27162716
}
27172717
NativeLibKind::WasmImportModule => {}

compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn collate_raw_dylibs_windows<'a>(
3131
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
3232

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

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

145-
let imports = dylib_table.entry(filename.clone()).or_default();
145+
let (stub_imports, stub_as_needed) =
146+
dylib_table.entry(filename.clone()).or_insert((Default::default(), true));
146147
for import in &lib.dll_imports {
147-
imports.insert(import.name, import);
148+
stub_imports.insert(import.name, import);
148149
}
150+
*stub_as_needed = *stub_as_needed && as_needed.unwrap_or(true);
149151
}
150152
}
151153
sess.dcx().abort_if_errors();
152154
dylib_table
153155
.into_iter()
154-
.map(|(name, imports)| {
155-
(name, imports.into_iter().map(|(_, import)| import.clone()).collect())
156+
.map(|(name, (imports, as_needed))| {
157+
(name, imports.into_iter().map(|(_, import)| import.clone()).collect(), as_needed)
156158
})
157159
.collect()
158160
}
@@ -161,10 +163,10 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
161163
sess: &Session,
162164
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
163165
raw_dylib_so_dir: &Path,
164-
) -> Vec<String> {
166+
) -> Vec<(String, bool)> {
165167
collate_raw_dylibs_elf(sess, used_libraries)
166168
.into_iter()
167-
.map(|(load_filename, raw_dylib_imports)| {
169+
.map(|(load_filename, raw_dylib_imports, as_needed)| {
168170
use std::hash::Hash;
169171

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

208-
temporary_lib_name
210+
(temporary_lib_name, as_needed)
209211
})
210212
.collect()
211213
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,10 @@ pub enum NativeLibKind {
307307
},
308308
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
309309
/// On Linux, it refers to a generated shared library stub.
310-
RawDylib,
310+
RawDylib {
311+
/// Whether the dynamic library will be linked only if it satisfies some undefined symbols
312+
as_needed: Option<bool>,
313+
},
311314
/// A macOS-specific kind of dynamic libraries.
312315
Framework {
313316
/// Whether the framework will be linked only if it satisfies some undefined symbols
@@ -330,11 +333,10 @@ impl NativeLibKind {
330333
NativeLibKind::Static { bundle, whole_archive } => {
331334
bundle.is_some() || whole_archive.is_some()
332335
}
333-
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
334-
as_needed.is_some()
335-
}
336-
NativeLibKind::RawDylib
337-
| NativeLibKind::Unspecified
336+
NativeLibKind::Dylib { as_needed }
337+
| NativeLibKind::Framework { as_needed }
338+
| NativeLibKind::RawDylib { as_needed } => as_needed.is_some(),
339+
NativeLibKind::Unspecified
338340
| NativeLibKind::LinkArg
339341
| NativeLibKind::WasmImportModule => false,
340342
}
@@ -347,7 +349,9 @@ impl NativeLibKind {
347349
pub fn is_dllimport(&self) -> bool {
348350
matches!(
349351
self,
350-
NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
352+
NativeLibKind::Dylib { .. }
353+
| NativeLibKind::RawDylib { .. }
354+
| NativeLibKind::Unspecified
351355
)
352356
}
353357
}

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'tcx> Collector<'tcx> {
218218
.flatten()
219219
{
220220
let dll_imports = match attr.kind {
221-
NativeLibKind::RawDylib => foreign_items
221+
NativeLibKind::RawDylib { .. } => foreign_items
222222
.iter()
223223
.map(|&child_item| {
224224
self.build_dll_import(

compiler/rustc_session/src/config/native_libs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li
135135
),
136136

137137
("as-needed", NativeLibKind::Dylib { as_needed })
138-
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
138+
| ("as-needed", NativeLibKind::Framework { as_needed })
139+
| ("as-needed", NativeLibKind::RawDylib { as_needed }) => {
139140
cx.on_unstable_value(
140141
"linking modifier `as-needed` is unstable",
141142
", the `-Z unstable-options` flag must also be passed to use it",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//@ only-elf
2+
//@ needs-dynamic-linking
3+
4+
//@ only-gnu
5+
//@ only-x86_64
6+
//@ revisions: as_needed no_as_needed no_modifier merge_1 merge_2 merge_3 merge_4
7+
8+
//@ [as_needed] run-pass
9+
//@ [no_as_needed] run-fail
10+
//@ [no_modifier] run-pass
11+
//@ [merge_1] run-fail
12+
//@ [merge_2] run-fail
13+
//@ [merge_3] run-fail
14+
//@ [merge_4] run-pass
15+
16+
#![allow(incomplete_features)]
17+
#![feature(raw_dylib_elf)]
18+
#![feature(native_link_modifiers_as_needed)]
19+
20+
#[cfg_attr(
21+
as_needed,
22+
link(name = "taiqannf1y28z2rw", kind = "raw-dylib", modifiers = "+as-needed")
23+
)]
24+
#[cfg_attr(
25+
no_as_needed,
26+
link(name = "taiqannf1y28z2rw", kind = "raw-dylib", modifiers = "-as-needed")
27+
)]
28+
#[cfg_attr(no_modifier, link(name = "taiqannf1y28z2rw", kind = "raw-dylib"))]
29+
unsafe extern "C" {}
30+
31+
#[cfg_attr(merge_1, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
32+
#[cfg_attr(merge_2, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
33+
#[cfg_attr(merge_3, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
34+
#[cfg_attr(merge_4, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
35+
unsafe extern "C" {}
36+
37+
#[cfg_attr(merge_1, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
38+
#[cfg_attr(merge_2, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
39+
#[cfg_attr(merge_3, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "-as-needed"))]
40+
#[cfg_attr(merge_4, link(name = "k9nm7qxoa79bg7e6", kind = "raw-dylib", modifiers = "+as-needed"))]
41+
unsafe extern "C" {}
42+
43+
fn main() {}

0 commit comments

Comments
 (0)