support link modifier as-needed for raw-dylib-elf

This commit is contained in:
usamoi
2025-08-26 16:24:29 +08:00
parent 839222065a
commit 21dd997aec
8 changed files with 82 additions and 31 deletions

View File

@@ -1490,7 +1490,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
@@ -2364,13 +2364,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
@@ -2411,13 +2411,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);
}
}
@@ -2726,7 +2726,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 => {}

View File

@@ -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();
@@ -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 {
@@ -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()
}
@@ -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.
@@ -205,7 +207,7 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
});
};
temporary_lib_name
(temporary_lib_name, as_needed)
})
.collect()
}