Skip to content

Commit fd946df

Browse files
committed
Support static libraries with names other than libfoo.a
Required for rust-lang/rust#29520 Signed-off-by: Peter Atashian <[email protected]>
1 parent cdbc76b commit fd946df

File tree

1 file changed

+41
-6
lines changed

1 file changed

+41
-6
lines changed

src/cargo/ops/cargo_rustc/context.rs

+41-6
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ pub struct Context<'a, 'cfg: 'a> {
4242
target: Option<Layout>,
4343
target_triple: String,
4444
host_dylib: Option<(String, String)>,
45+
host_staticlib: Option<(String, String)>,
4546
host_exe: String,
4647
package_set: &'a PackageSet,
4748
target_dylib: Option<(String, String)>,
49+
target_staticlib: Option<(String, String)>,
4850
target_exe: String,
4951
profiles: &'a Profiles,
5052
}
@@ -60,10 +62,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
6062
profiles: &'a Profiles) -> CargoResult<Context<'a, 'cfg>> {
6163
let target = build_config.requested_target.clone();
6264
let target = target.as_ref().map(|s| &s[..]);
63-
let (target_dylib, target_exe) = try!(Context::filename_parts(target,
65+
let (target_dylib, target_staticlib, target_exe) = try!(Context::filename_parts(target,
6466
config));
65-
let (host_dylib, host_exe) = if build_config.requested_target.is_none() {
66-
(target_dylib.clone(), target_exe.clone())
67+
let (host_dylib, host_staticlib, host_exe) = if build_config.requested_target.is_none() {
68+
(target_dylib.clone(), target_staticlib.clone(), target_exe.clone())
6769
} else {
6870
try!(Context::filename_parts(None, config))
6971
};
@@ -82,8 +84,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
8284
package_set: deps,
8385
config: config,
8486
target_dylib: target_dylib,
87+
target_staticlib: target_staticlib,
8588
target_exe: target_exe,
8689
host_dylib: host_dylib,
90+
host_staticlib: host_staticlib,
8791
host_exe: host_exe,
8892
compilation: Compilation::new(config),
8993
build_state: Arc::new(BuildState::new(&build_config, deps)),
@@ -100,11 +104,12 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
100104
/// Run `rustc` to discover the dylib prefix/suffix for the target
101105
/// specified as well as the exe suffix
102106
fn filename_parts(target: Option<&str>, cfg: &Config)
103-
-> CargoResult<(Option<(String, String)>, String)> {
107+
-> CargoResult<(Option<(String, String)>, Option<(String, String)>, String)> {
104108
let mut process = util::process(cfg.rustc());
105109
process.arg("-")
106110
.arg("--crate-name").arg("_")
107111
.arg("--crate-type").arg("dylib")
112+
.arg("--crate-type").arg("staticlib")
108113
.arg("--crate-type").arg("bin")
109114
.arg("--print=file-names")
110115
.env_remove("RUST_LOG");
@@ -117,6 +122,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
117122
let output = str::from_utf8(&output.stdout).unwrap();
118123
let mut lines = output.lines();
119124
let nodylib = Regex::new("unsupported crate type.*dylib").unwrap();
125+
let nostaticlib = Regex::new("unsupported crate type.*staticlib").unwrap();
120126
let nobin = Regex::new("unsupported crate type.*bin").unwrap();
121127
let dylib = if nodylib.is_match(error) {
122128
None
@@ -127,14 +133,23 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
127133
"rustc --print-file-name output has changed");
128134
Some((dylib_parts[0].to_string(), dylib_parts[1].to_string()))
129135
};
136+
let staticlib = if nostaticlib.is_match(error) {
137+
None
138+
} else {
139+
let staticlib_parts: Vec<&str> = lines.next().unwrap().trim()
140+
.split('_').collect();
141+
assert!(staticlib_parts.len() == 2,
142+
"rustc --print-file-name output has changed");
143+
Some((staticlib_parts[0].to_string(), staticlib_parts[1].to_string()))
144+
};
130145

131146
let exe_suffix = if nobin.is_match(error) {
132147
String::new()
133148
} else {
134149
lines.next().unwrap().trim()
135150
.split('_').skip(1).next().unwrap().to_string()
136151
};
137-
Ok((dylib, exe_suffix))
152+
Ok((dylib, staticlib, exe_suffix))
138153
}
139154

140155
/// Prepare this context, ensuring that all filesystem directories are in
@@ -202,6 +217,22 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
202217
}
203218
}
204219

220+
/// Return the (prefix, suffix) pair for static libraries.
221+
///
222+
/// If `plugin` is true, the pair corresponds to the host platform,
223+
/// otherwise it corresponds to the target platform.
224+
fn staticlib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
225+
let (triple, pair) = if kind == Kind::Host {
226+
(&self.config.rustc_info().host, &self.host_staticlib)
227+
} else {
228+
(&self.target_triple, &self.target_staticlib)
229+
};
230+
match *pair {
231+
None => bail!("staticlib outputs are not supported for {}", triple),
232+
Some((ref s1, ref s2)) => Ok((s1, s2)),
233+
}
234+
}
235+
205236
/// Return the target triple which this context is targeting.
206237
pub fn target_triple(&self) -> &str {
207238
&self.target_triple
@@ -277,7 +308,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
277308
}
278309
LibKind::Lib |
279310
LibKind::Rlib => ret.push(format!("lib{}.rlib", stem)),
280-
LibKind::StaticLib => ret.push(format!("lib{}.a", stem)),
311+
LibKind::StaticLib => {
312+
if let Ok((prefix, suffix)) = self.staticlib(unit.kind) {
313+
ret.push(format!("{}{}{}", prefix, stem, suffix));
314+
}
315+
}
281316
}
282317
}
283318
}

0 commit comments

Comments
 (0)