Skip to content

Commit 432565c

Browse files
committed
Support for versioned dylibs
Right now, rustc fails when trying to link against a versioned dylib crate (e.g. libsomecrate.so.0.1). This patch tries to address this by replacing the simple ends_with dll_suffix check with a better one.
1 parent 00d5e42 commit 432565c

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2379,7 +2379,16 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
23792379
if let Some(dir) = parent {
23802380
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
23812381
}
2382-
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
2382+
let filename = cratepath.file_name().unwrap().to_str().unwrap();
2383+
// test if dll_suffix is found within filename (should be, but if it
2384+
// isn't falls back to just getting the file stem). Then just gets the
2385+
// substring from the beginning to the suffix. This is better than just
2386+
// getting the filestem, as it respects versioned libraries.
2387+
let filestem = filename
2388+
.find(&sess.target.dll_suffix)
2389+
.map(|idx| filename.get(0..idx))
2390+
.flatten()
2391+
.unwrap_or(cratepath.file_stem().unwrap().to_str().unwrap());
23832392
cmd.link_rust_dylib(
23842393
Symbol::intern(&unlib(&sess.target, filestem)),
23852394
parent.unwrap_or_else(|| Path::new("")),

compiler/rustc_metadata/src/locator.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,25 @@ impl<'a> CrateLocator<'a> {
365365
self.find_library_crate("", &mut seen_paths)
366366
}
367367

368+
/// Returns true if `file` has a suffix that could be a valid dylib
369+
/// Example (assuming target has .so as dll_suffix):
370+
/// - `libsomecrate.asdf` -> `false`
371+
/// - `libsomecrate.so` -> `true`
372+
/// - `libsomecrate.so.0.1` -> `true`
373+
/// - `libsomecrate.so.a.4` -> `false`
374+
fn test_dylib_suffix(&self, file: &str) -> bool {
375+
// test if the targets dll_suffix is found within the filename. If it
376+
// is check if all of the chars following it are either in range 0x30
377+
// to 0x39 (0-9) or 0x2E (.).
378+
match file.find(&self.target.dll_suffix) {
379+
Some(idx) => file
380+
.chars()
381+
.skip(idx + self.target.dll_suffix.len())
382+
.all(|c| c as u32 >= 0x30 && c as u32 <= 0x39 || c as u32 == 0x2E),
383+
None => false,
384+
}
385+
}
386+
368387
fn find_library_crate(
369388
&mut self,
370389
extra_prefix: &str,
@@ -402,7 +421,7 @@ impl<'a> CrateLocator<'a> {
402421
(&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
403422
} else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
404423
(&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
405-
} else if file.starts_with(&dylib_prefix) && file.ends_with(&self.target.dll_suffix) {
424+
} else if file.starts_with(&dylib_prefix) && self.test_dylib_suffix(file) {
406425
(
407426
&file[(dylib_prefix.len())..(file.len() - self.target.dll_suffix.len())],
408427
CrateFlavor::Dylib,
@@ -681,8 +700,7 @@ impl<'a> CrateLocator<'a> {
681700
};
682701

683702
if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta"))
684-
|| file.starts_with(&self.target.dll_prefix)
685-
&& file.ends_with(&self.target.dll_suffix)
703+
|| file.starts_with(&self.target.dll_prefix) && self.test_dylib_suffix(file)
686704
{
687705
// Make sure there's at most one rlib and at most one dylib.
688706
// Note to take care and match against the non-canonicalized name:

0 commit comments

Comments
 (0)