Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 15d33db

Browse files
committedOct 27, 2021
Preliminary support for verbatim linking of crates
Due to the fact that if we were not using verbatim linking, linking against a versioned crate will only work if a unversioned symlink to the versioned one is part of the searchpath. This is "preliminary" as right now it only uses the whole filename for GNU-style linkers. It should however, be expanded to any linker that supports verbatim linking. Also added suggestions from @wesleywiser.
1 parent 432565c commit 15d33db

File tree

3 files changed

+42
-43
lines changed

3 files changed

+42
-43
lines changed
 

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

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
33
use rustc_errors::{ErrorReported, Handler};
44
use rustc_fs_util::fix_windows_verbatim_for_gcc;
55
use rustc_hir::def_id::CrateNum;
6+
use rustc_metadata::locator::{get_dylib_symbol_name, unlib};
67
use rustc_middle::middle::dependency_format::Linkage;
78
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
89
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -17,7 +18,7 @@ use rustc_span::symbol::Symbol;
1718
use rustc_target::abi::Endian;
1819
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
1920
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
20-
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
21+
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet};
2122

2223
use super::archive::{find_library, ArchiveBuilder};
2324
use super::command::Command;
@@ -2252,11 +2253,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
22522253
add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
22532254
}
22542255

2255-
// Converts a library file-stem into a cc -l argument
2256-
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
2257-
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
2258-
}
2259-
22602256
// Adds the static "rlib" versions of all crates to the command line.
22612257
// There's a bit of magic which happens here specifically related to LTO,
22622258
// namely that we remove upstream object files.
@@ -2380,19 +2376,9 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
23802376
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
23812377
}
23822378
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());
2392-
cmd.link_rust_dylib(
2393-
Symbol::intern(&unlib(&sess.target, filestem)),
2394-
parent.unwrap_or_else(|| Path::new("")),
2395-
);
2379+
let symbol_name = get_dylib_symbol_name(filename, &sess.target)
2380+
.unwrap_or(unlib(&sess.target, cratepath.file_stem().unwrap().to_str().unwrap()));
2381+
cmd.link_rust_dylib(Symbol::intern(symbol_name), cratepath);
23962382
}
23972383
}
23982384

‎compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,9 @@ impl<'a> Linker for GccLinker<'a> {
464464
self.linker_arg("-znorelro");
465465
}
466466

467-
fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
467+
fn link_rust_dylib(&mut self, _lib: Symbol, path: &Path) {
468468
self.hint_dynamic();
469-
self.cmd.arg(format!("-l{}", lib));
469+
self.cmd.arg(format!("-l:{}", path.file_name().unwrap().to_str().unwrap()));
470470
}
471471

472472
fn link_framework(&mut self, framework: Symbol, as_needed: bool) {
@@ -837,7 +837,7 @@ impl<'a> Linker for MsvcLinker<'a> {
837837
// check to see if the file is there and just omit linking to it if it's
838838
// not present.
839839
let name = format!("{}.dll.lib", lib);
840-
if path.join(&name).exists() {
840+
if path.parent().unwrap_or_else(|| Path::new("")).join(&name).exists() {
841841
self.cmd.arg(name);
842842
}
843843
}

‎compiler/rustc_metadata/src/locator.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,35 @@ use std::path::{Path, PathBuf};
238238
use std::{cmp, fmt, fs};
239239
use tracing::{debug, info, warn};
240240

241+
// Converts a library file-stem into a cc -l argument
242+
pub fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
243+
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
244+
}
245+
246+
/// Returns Some(symbol_name) if `file` could be a valid dylib
247+
/// Example (assuming target is GNU/Linux):
248+
/// - `libsomecrate.asdf` -> `None`
249+
/// - `libsomecrate.so` -> `Some(somecreate)`
250+
/// - `libsomecrate.so.0.1` -> `Some(somecreate)`
251+
/// - `libsomecrate.so.a.4` -> `None`
252+
pub fn get_dylib_symbol_name<'a>(file: &'a str, target: &Target) -> Option<&'a str> {
253+
// test if the targets dll_suffix is found within the filename. If it
254+
// is check if all of the chars following it are either a digit (0-9)
255+
// or a dot.
256+
file.find(&target.dll_suffix)
257+
.map(|idx| {
258+
match file
259+
.chars()
260+
.skip(idx + idx + target.dll_suffix.len())
261+
.all(|c| c.is_ascii_digit() || c == '.')
262+
{
263+
true => file.get(0..idx).map(|s| unlib(target, s)),
264+
false => None,
265+
}
266+
})
267+
.flatten()
268+
}
269+
241270
#[derive(Clone)]
242271
crate struct CrateLocator<'a> {
243272
// Immutable per-session configuration.
@@ -365,25 +394,6 @@ impl<'a> CrateLocator<'a> {
365394
self.find_library_crate("", &mut seen_paths)
366395
}
367396

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-
387397
fn find_library_crate(
388398
&mut self,
389399
extra_prefix: &str,
@@ -421,7 +431,9 @@ impl<'a> CrateLocator<'a> {
421431
(&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
422432
} else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
423433
(&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
424-
} else if file.starts_with(&dylib_prefix) && self.test_dylib_suffix(file) {
434+
} else if file.starts_with(&dylib_prefix)
435+
&& get_dylib_symbol_name(file, &self.target).is_some()
436+
{
425437
(
426438
&file[(dylib_prefix.len())..(file.len() - self.target.dll_suffix.len())],
427439
CrateFlavor::Dylib,
@@ -700,7 +712,8 @@ impl<'a> CrateLocator<'a> {
700712
};
701713

702714
if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta"))
703-
|| file.starts_with(&self.target.dll_prefix) && self.test_dylib_suffix(file)
715+
|| file.starts_with(&self.target.dll_prefix)
716+
&& get_dylib_symbol_name(file, &self.target).is_some()
704717
{
705718
// Make sure there's at most one rlib and at most one dylib.
706719
// Note to take care and match against the non-canonicalized name:

0 commit comments

Comments
 (0)
Please sign in to comment.