Skip to content

Commit c5a6f06

Browse files
committed
Clean up TargetInfo
1 parent 1dd0215 commit c5a6f06

File tree

6 files changed

+122
-117
lines changed

6 files changed

+122
-117
lines changed

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
127127
Kind::Host => &self.host_info,
128128
Kind::Target => &self.target_info,
129129
};
130-
info.cfg().unwrap_or(&[])
130+
info.cfg()
131131
}
132132

133133
/// Gets the host architecture triple.

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,34 @@ use crate::core::TargetKind;
99
use crate::util::CfgExpr;
1010
use crate::util::{CargoResult, CargoResultExt, Cfg, Config, ProcessBuilder, Rustc};
1111

12+
/// Information about the platform target gleaned from querying rustc.
13+
///
14+
/// The `BuildContext` keeps two of these, one for the host and one for the
15+
/// target. If no target is specified, it uses a clone from the host.
1216
#[derive(Clone)]
1317
pub struct TargetInfo {
14-
crate_type_process: Option<ProcessBuilder>,
18+
/// A base process builder for discovering crate type information. In
19+
/// particular, this is used to determine the output filename prefix and
20+
/// suffix for a crate type.
21+
crate_type_process: ProcessBuilder,
22+
/// Cache of output filename prefixes and suffixes.
23+
///
24+
/// The key is the crate type name (like `cdylib`) and the value is
25+
/// `Some((prefix, suffix))`, for example `libcargo.so` would be
26+
/// `Some(("lib", ".so")). The value is `None` if the crate type is not
27+
/// supported.
1528
crate_types: RefCell<HashMap<String, Option<(String, String)>>>,
16-
cfg: Option<Vec<Cfg>>,
17-
pub sysroot_libdir: Option<PathBuf>,
29+
/// `cfg` information extracted from `rustc --print=cfg`.
30+
cfg: Vec<Cfg>,
31+
/// Path to the "lib" directory in the sysroot.
32+
pub sysroot_libdir: PathBuf,
33+
/// Extra flags to pass to `rustc`, see `env_args`.
1834
pub rustflags: Vec<String>,
35+
/// Extra flags to pass to `rustdoc`, see `env_args`.
1936
pub rustdocflags: Vec<String>,
2037
}
2138

22-
/// Type of each file generated by a Unit.
39+
/// Kind of each file generated by a Unit, part of `FileType`.
2340
#[derive(Clone, PartialEq, Eq, Debug)]
2441
pub enum FileFlavor {
2542
/// Not a special file type.
@@ -30,9 +47,13 @@ pub enum FileFlavor {
3047
DebugInfo,
3148
}
3249

50+
/// Type of each file generated by a Unit.
3351
pub struct FileType {
52+
/// The kind of file.
3453
pub flavor: FileFlavor,
54+
/// The suffix for the file (for example, `.rlib`).
3555
suffix: String,
56+
/// The prefix for the file (for example, `lib`).
3657
prefix: String,
3758
// Wasm bin target will generate two files in deps such as
3859
// "web-stuff.js" and "web_stuff.wasm". Note the different usages of
@@ -92,60 +113,51 @@ impl TargetInfo {
92113
process.arg("--crate-type").arg(crate_type);
93114
}
94115

95-
let mut with_cfg = process.clone();
96-
with_cfg.arg("--print=sysroot");
97-
with_cfg.arg("--print=cfg");
116+
process.arg("--print=sysroot");
117+
process.arg("--print=cfg");
98118

99-
let mut has_cfg_and_sysroot = true;
100119
let (output, error) = rustc
101-
.cached_output(&with_cfg)
102-
.or_else(|_| {
103-
has_cfg_and_sysroot = false;
104-
rustc.cached_output(&process)
105-
})
120+
.cached_output(&process)
106121
.chain_err(|| "failed to run `rustc` to learn about target-specific information")?;
107122

108123
let mut lines = output.lines();
109124
let mut map = HashMap::new();
110125
for crate_type in KNOWN_CRATE_TYPES {
111-
let out = parse_crate_type(crate_type, &error, &mut lines)?;
126+
let out = parse_crate_type(crate_type, &process, &output, &error, &mut lines)?;
112127
map.insert(crate_type.to_string(), out);
113128
}
114129

115-
let mut sysroot_libdir = None;
116-
if has_cfg_and_sysroot {
117-
let line = match lines.next() {
118-
Some(line) => line,
119-
None => failure::bail!(
120-
"output of --print=sysroot missing when learning about \
121-
target-specific information from rustc"
122-
),
123-
};
124-
let mut rustlib = PathBuf::from(line);
125-
if kind == Kind::Host {
130+
let line = match lines.next() {
131+
Some(line) => line,
132+
None => failure::bail!(
133+
"output of --print=sysroot missing when learning about \
134+
target-specific information from rustc\n{}",
135+
output_err_info(&process, &output, &error)
136+
),
137+
};
138+
let mut rustlib = PathBuf::from(line);
139+
let sysroot_libdir = match kind {
140+
Kind::Host => {
126141
if cfg!(windows) {
127142
rustlib.push("bin");
128143
} else {
129144
rustlib.push("lib");
130145
}
131-
sysroot_libdir = Some(rustlib);
132-
} else {
146+
rustlib
147+
}
148+
Kind::Target => {
133149
rustlib.push("lib");
134150
rustlib.push("rustlib");
135151
rustlib.push(target_triple);
136152
rustlib.push("lib");
137-
sysroot_libdir = Some(rustlib);
153+
rustlib
138154
}
139-
}
140-
141-
let cfg = if has_cfg_and_sysroot {
142-
Some(lines.map(Cfg::from_str).collect::<CargoResult<Vec<_>>>()?)
143-
} else {
144-
None
145155
};
146156

157+
let cfg = lines.map(Cfg::from_str).collect::<CargoResult<Vec<_>>>()?;
158+
147159
Ok(TargetInfo {
148-
crate_type_process: Some(crate_type_process),
160+
crate_type_process,
149161
crate_types: RefCell::new(map),
150162
sysroot_libdir,
151163
// recalculate `rustflags` from above now that we have `cfg`
@@ -154,24 +166,24 @@ impl TargetInfo {
154166
config,
155167
requested_target,
156168
&rustc.host,
157-
cfg.as_ref().map(|v| v.as_ref()),
169+
Some(&cfg),
158170
kind,
159171
"RUSTFLAGS",
160172
)?,
161173
rustdocflags: env_args(
162174
config,
163175
requested_target,
164176
&rustc.host,
165-
cfg.as_ref().map(|v| v.as_ref()),
177+
Some(&cfg),
166178
kind,
167179
"RUSTDOCFLAGS",
168180
)?,
169181
cfg,
170182
})
171183
}
172184

173-
pub fn cfg(&self) -> Option<&[Cfg]> {
174-
self.cfg.as_ref().map(|v| v.as_ref())
185+
pub fn cfg(&self) -> &[Cfg] {
186+
&self.cfg
175187
}
176188

177189
pub fn file_types(
@@ -255,21 +267,26 @@ impl TargetInfo {
255267
}
256268

257269
fn discover_crate_type(&self, crate_type: &str) -> CargoResult<Option<(String, String)>> {
258-
let mut process = self.crate_type_process.clone().unwrap();
270+
let mut process = self.crate_type_process.clone();
259271

260272
process.arg("--crate-type").arg(crate_type);
261273

262274
let output = process.exec_with_output().chain_err(|| {
263275
format!(
264-
"failed to run `rustc` to learn about \
265-
crate-type {} information",
276+
"failed to run `rustc` to learn about crate-type {} information",
266277
crate_type
267278
)
268279
})?;
269280

270281
let error = str::from_utf8(&output.stderr).unwrap();
271282
let output = str::from_utf8(&output.stdout).unwrap();
272-
Ok(parse_crate_type(crate_type, error, &mut output.lines())?)
283+
Ok(parse_crate_type(
284+
crate_type,
285+
&process,
286+
output,
287+
error,
288+
&mut output.lines(),
289+
)?)
273290
}
274291
}
275292

@@ -284,6 +301,8 @@ impl TargetInfo {
284301
// are two files for bin (`.wasm` and `.js`)).
285302
fn parse_crate_type(
286303
crate_type: &str,
304+
cmd: &ProcessBuilder,
305+
output: &str,
287306
error: &str,
288307
lines: &mut str::Lines<'_>,
289308
) -> CargoResult<Option<(String, String)>> {
@@ -297,24 +316,41 @@ fn parse_crate_type(
297316
let line = match lines.next() {
298317
Some(line) => line,
299318
None => failure::bail!(
300-
"malformed output when learning about \
301-
crate-type {} information",
302-
crate_type
319+
"malformed output when learning about crate-type {} information\n{}",
320+
crate_type,
321+
output_err_info(cmd, output, error)
303322
),
304323
};
305324
let mut parts = line.trim().split("___");
306325
let prefix = parts.next().unwrap();
307326
let suffix = match parts.next() {
308327
Some(part) => part,
309328
None => failure::bail!(
310-
"output of --print=file-names has changed in \
311-
the compiler, cannot parse"
329+
"output of --print=file-names has changed in the compiler, cannot parse\n{}",
330+
output_err_info(cmd, output, error)
312331
),
313332
};
314333

315334
Ok(Some((prefix.to_string(), suffix.to_string())))
316335
}
317336

337+
/// Helper for creating an error message when parsing rustc output fails.
338+
fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
339+
let mut result = format!("command was: {}\n", cmd);
340+
if !stdout.is_empty() {
341+
result.push_str("\n--- stdout\n");
342+
result.push_str(stdout);
343+
}
344+
if !stderr.is_empty() {
345+
result.push_str("\n--- stderr\n");
346+
result.push_str(stderr);
347+
}
348+
if stdout.is_empty() && stderr.is_empty() {
349+
result.push_str("(no output received)");
350+
}
351+
result
352+
}
353+
318354
/// Acquire extra flags to pass to the compiler from various locations.
319355
///
320356
/// The locations are:

src/cargo/core/compiler/compilation.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ pub struct Compilation<'cfg> {
4646
pub host_deps_output: PathBuf,
4747

4848
/// The path to rustc's own libstd
49-
pub host_dylib_path: Option<PathBuf>,
49+
pub host_dylib_path: PathBuf,
5050

5151
/// The path to libstd for the target
52-
pub target_dylib_path: Option<PathBuf>,
52+
pub target_dylib_path: PathBuf,
5353

5454
/// Extra environment variables that were passed to compilations and should
5555
/// be passed to future invocations of programs.
@@ -189,14 +189,14 @@ impl<'cfg> Compilation<'cfg> {
189189
) -> CargoResult<ProcessBuilder> {
190190
let mut search_path = if is_host {
191191
let mut search_path = vec![self.host_deps_output.clone()];
192-
search_path.extend(self.host_dylib_path.clone());
192+
search_path.push(self.host_dylib_path.clone());
193193
search_path
194194
} else {
195195
let mut search_path =
196196
super::filter_dynamic_search_path(self.native_dirs.iter(), &self.root_output);
197197
search_path.push(self.deps_output.clone());
198198
search_path.push(self.root_output.clone());
199-
search_path.extend(self.target_dylib_path.clone());
199+
search_path.push(self.target_dylib_path.clone());
200200
search_path
201201
};
202202

@@ -286,29 +286,27 @@ fn target_runner(bcx: &BuildContext<'_, '_>) -> CargoResult<Option<(PathBuf, Vec
286286
}
287287

288288
// try target.'cfg(...)'.runner
289-
if let Some(target_cfg) = bcx.target_info.cfg() {
290-
if let Some(table) = bcx.config.get_table("target")? {
291-
let mut matching_runner = None;
292-
293-
for key in table.val.keys() {
294-
if CfgExpr::matches_key(key, target_cfg) {
295-
let key = format!("target.{}.runner", key);
296-
if let Some(runner) = bcx.config.get_path_and_args(&key)? {
297-
// more than one match, error out
298-
if matching_runner.is_some() {
299-
failure::bail!(
300-
"several matching instances of `target.'cfg(..)'.runner` \
301-
in `.cargo/config`"
302-
)
303-
}
304-
305-
matching_runner = Some(runner.val);
289+
if let Some(table) = bcx.config.get_table("target")? {
290+
let mut matching_runner = None;
291+
292+
for key in table.val.keys() {
293+
if CfgExpr::matches_key(key, bcx.target_info.cfg()) {
294+
let key = format!("target.{}.runner", key);
295+
if let Some(runner) = bcx.config.get_path_and_args(&key)? {
296+
// more than one match, error out
297+
if matching_runner.is_some() {
298+
failure::bail!(
299+
"several matching instances of `target.'cfg(..)'.runner` \
300+
in `.cargo/config`"
301+
)
306302
}
303+
304+
matching_runner = Some(runner.val);
307305
}
308306
}
309-
310-
return Ok(matching_runner);
311307
}
308+
309+
return Ok(matching_runner);
312310
}
313311

314312
Ok(None)

src/cargo/core/dependency.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,10 @@ impl Dependency {
459459
}
460460

461461
impl Platform {
462-
pub fn matches(&self, name: &str, cfg: Option<&[Cfg]>) -> bool {
462+
pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool {
463463
match *self {
464464
Platform::Name(ref p) => p == name,
465-
Platform::Cfg(ref p) => match cfg {
466-
Some(cfg) => p.matches(cfg),
467-
None => false,
468-
},
465+
Platform::Cfg(ref p) => p.matches(cfg),
469466
}
470467
}
471468
}

0 commit comments

Comments
 (0)