Skip to content

Commit 49e1fd8

Browse files
committed
Support for forcing a specific --extern crate type
As of now, rustc tries to detect what kind of crate it is linking against based on it's file prefix and extension. With this patch, rustc offers the possibilty of forcing a specific crate type in cases the filename is not inline with rustc's expectations, by --extern kind:name=/path/to/name.ext. `kind` may be "rlib", "rmeta" or "dylib".
1 parent 93e8201 commit 49e1fd8

File tree

4 files changed

+82
-38
lines changed

4 files changed

+82
-38
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2365,7 +2365,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
23652365
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
23662366
cmd.link_rust_dylib(
23672367
Symbol::intern(&unlib(&sess.target, filestem)),
2368-
parent.unwrap_or_else(|| Path::new("")),
2368+
cratepath,
23692369
);
23702370
}
23712371
}

compiler/rustc_codegen_ssa/src/back/linker.rs

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

487-
fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
487+
fn link_rust_dylib(&mut self, _lib: Symbol, path: &Path) {
488488
self.hint_dynamic();
489-
self.cmd.arg(format!("-l{}", lib));
489+
self.cmd.arg(format!("-l:{}", path.file_name().unwrap().to_str().unwrap()));
490490
}
491491

492492
fn link_framework(&mut self, framework: Symbol, as_needed: bool) {
@@ -846,7 +846,7 @@ impl<'a> Linker for MsvcLinker<'a> {
846846
// check to see if the file is there and just omit linking to it if it's
847847
// not present.
848848
let name = format!("{}.dll.lib", lib);
849-
if path.join(&name).exists() {
849+
if path.parent().unwrap_or_else(|| Path::new("")).join(&name).exists() {
850850
self.cmd.arg(name);
851851
}
852852
}

compiler/rustc_metadata/src/locator.rs

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ use rustc_data_structures::owning_ref::OwningRef;
221221
use rustc_data_structures::svh::Svh;
222222
use rustc_data_structures::sync::MetadataRef;
223223
use rustc_errors::{struct_span_err, FatalError};
224-
use rustc_session::config::{self, CrateType};
224+
use rustc_session::config::{self, CrateType, CrateFlavor};
225225
use rustc_session::cstore::{CrateSource, MetadataLoader};
226226
use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
227227
use rustc_session::search_paths::PathKind;
@@ -254,6 +254,7 @@ crate struct CrateLocator<'a> {
254254
pub triple: TargetTriple,
255255
pub filesearch: FileSearch<'a>,
256256
pub is_proc_macro: bool,
257+
pub extern_flavor: Option<CrateFlavor>,
257258

258259
// Mutable in-progress state or output.
259260
crate_rejections: CrateRejections,
@@ -271,23 +272,6 @@ impl CratePaths {
271272
}
272273
}
273274

274-
#[derive(Copy, Clone, PartialEq)]
275-
crate enum CrateFlavor {
276-
Rlib,
277-
Rmeta,
278-
Dylib,
279-
}
280-
281-
impl fmt::Display for CrateFlavor {
282-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283-
f.write_str(match *self {
284-
CrateFlavor::Rlib => "rlib",
285-
CrateFlavor::Rmeta => "rmeta",
286-
CrateFlavor::Dylib => "dylib",
287-
})
288-
}
289-
}
290-
291275
impl<'a> CrateLocator<'a> {
292276
crate fn new(
293277
sess: &'a Session,
@@ -340,6 +324,7 @@ impl<'a> CrateLocator<'a> {
340324
sess.target_filesearch(path_kind)
341325
},
342326
is_proc_macro: false,
327+
extern_flavor: sess.opts.externs.get(crate_name.as_str()).map(|entry| entry.kind).flatten(),
343328
crate_rejections: CrateRejections::default(),
344329
}
345330
}
@@ -399,11 +384,14 @@ impl<'a> CrateLocator<'a> {
399384
None => return FileDoesntMatch,
400385
Some(file) => file,
401386
};
402-
let (hash, found_kind) = if file.starts_with(&rlib_prefix) && file.ends_with(".rlib") {
387+
let (hash, found_kind) = if self.extern_flavor == Some(CrateFlavor::Rlib) ||
388+
file.starts_with(&rlib_prefix) && file.ends_with(".rlib") {
403389
(&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
404-
} else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
390+
} else if self.extern_flavor == Some(CrateFlavor::Rmeta) ||
391+
file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
405392
(&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
406-
} else if file.starts_with(&dylib_prefix) && file.ends_with(&self.target.dll_suffix) {
393+
} else if self.extern_flavor == Some(CrateFlavor::Dylib) ||
394+
file.starts_with(&dylib_prefix) && file.ends_with(&self.target.dll_suffix) {
407395
(
408396
&file[(dylib_prefix.len())..(file.len() - self.target.dll_suffix.len())],
409397
CrateFlavor::Dylib,
@@ -691,7 +679,7 @@ impl<'a> CrateLocator<'a> {
691679
}
692680
};
693681

694-
if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta"))
682+
if self.extern_flavor.is_some() || file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta"))
695683
|| file.starts_with(&self.target.dll_prefix)
696684
&& file.ends_with(&self.target.dll_suffix)
697685
{
@@ -704,9 +692,11 @@ impl<'a> CrateLocator<'a> {
704692
// rmetas as dylibs.
705693
let loc_canon = loc.canonicalized().clone();
706694
let loc = loc.original();
707-
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
695+
if self.extern_flavor == Some(CrateFlavor::Rlib) ||
696+
loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
708697
rlibs.insert(loc_canon, PathKind::ExternFlag);
709-
} else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
698+
} else if self.extern_flavor == Some(CrateFlavor::Rmeta) ||
699+
loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
710700
rmetas.insert(loc_canon, PathKind::ExternFlag);
711701
} else {
712702
dylibs.insert(loc_canon, PathKind::ExternFlag);

compiler/rustc_session/src/config.rs

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,11 @@ pub struct ExternEntry {
460460
/// This can be disabled with the `noprelude` option like
461461
/// `--extern noprelude:name`.
462462
pub add_prelude: bool,
463+
/// Link the entry as a specific kind of dependency.
464+
///
465+
/// If it is `None`, then rustc tries to automatically
466+
/// detect the correct kind based on fil extension.
467+
pub kind: Option<CrateFlavor>,
463468
}
464469

465470
#[derive(Clone, Debug)]
@@ -477,6 +482,23 @@ pub enum ExternLocation {
477482
ExactPaths(BTreeSet<CanonicalizedPath>),
478483
}
479484

485+
#[derive(Copy, Clone, PartialEq, Debug)]
486+
pub enum CrateFlavor {
487+
Rlib,
488+
Rmeta,
489+
Dylib,
490+
}
491+
492+
impl fmt::Display for CrateFlavor {
493+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494+
f.write_str(match *self {
495+
CrateFlavor::Rlib => "rlib",
496+
CrateFlavor::Rmeta => "rmeta",
497+
CrateFlavor::Dylib => "dylib",
498+
})
499+
}
500+
}
501+
480502
/// Supplied source location of a dependency - for example in a build specification
481503
/// file like Cargo.toml. We support several syntaxes: if it makes sense to reference
482504
/// a file and line, then the build system can specify that. On the other hand, it may
@@ -519,7 +541,7 @@ impl Externs {
519541

520542
impl ExternEntry {
521543
fn new(location: ExternLocation) -> ExternEntry {
522-
ExternEntry { location, is_private_dep: false, add_prelude: false }
544+
ExternEntry { location, is_private_dep: false, add_prelude: false, kind: None }
523545
}
524546

525547
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
@@ -1963,18 +1985,27 @@ pub fn parse_externs(
19631985

19641986
let mut is_private_dep = false;
19651987
let mut add_prelude = true;
1988+
let mut crate_type: Option<CrateFlavor> = None;
19661989
if let Some(opts) = options {
1967-
if !is_unstable_enabled {
1968-
early_error(
1969-
error_format,
1970-
"the `-Z unstable-options` flag must also be passed to \
1971-
enable `--extern options",
1972-
);
1973-
}
19741990
for opt in opts.split(',') {
19751991
match opt {
1976-
"priv" => is_private_dep = true,
1992+
"priv" => {
1993+
if !is_unstable_enabled {
1994+
early_error(error_format,
1995+
"the `-Z unstable-options` flag must also be passed to \
1996+
enable the `priv:` `--extern option",
1997+
);
1998+
}
1999+
is_private_dep = true
2000+
},
19772001
"noprelude" => {
2002+
if !is_unstable_enabled {
2003+
early_error(error_format,
2004+
"the `-Z unstable-options` flag must also be passed to \
2005+
enable the `noprelude:` `--extern option",
2006+
);
2007+
}
2008+
19782009
if let ExternLocation::ExactPaths(_) = &entry.location {
19792010
add_prelude = false;
19802011
} else {
@@ -1983,7 +2014,25 @@ pub fn parse_externs(
19832014
"the `noprelude` --extern option requires a file path",
19842015
);
19852016
}
1986-
}
2017+
},
2018+
"rlib" => {
2019+
match crate_type {
2020+
None => crate_type = Some(CrateFlavor::Rlib),
2021+
Some(_) => early_error(error_format, "--extern can only take one kind of lib type")
2022+
};
2023+
},
2024+
"meta" => {
2025+
match crate_type {
2026+
None => crate_type = Some(CrateFlavor::Rmeta),
2027+
Some(_) => early_error(error_format, "--extern can only take one kind of lib type")
2028+
};
2029+
},
2030+
"dylib" => {
2031+
match crate_type {
2032+
None => crate_type = Some(CrateFlavor::Dylib),
2033+
Some(_) => early_error(error_format, "--extern can only take one kind of lib type")
2034+
};
2035+
},
19872036
_ => early_error(error_format, &format!("unknown --extern option `{}`", opt)),
19882037
}
19892038
}
@@ -1994,6 +2043,11 @@ pub fn parse_externs(
19942043
entry.is_private_dep |= is_private_dep;
19952044
// If any flag is missing `noprelude`, then add to the prelude.
19962045
entry.add_prelude |= add_prelude;
2046+
// If entry currently doesn't have a kind, but crate_type has, set it
2047+
// to crate_type.
2048+
if let Some(new_kind) = crate_type {
2049+
entry.kind.get_or_insert(new_kind);
2050+
}
19972051
}
19982052
Externs(externs)
19992053
}

0 commit comments

Comments
 (0)