Skip to content

Commit 19362a7

Browse files
committed
when learning target information, run a little fixpoint iteration loop
1 parent 1a07767 commit 19362a7

File tree

1 file changed

+109
-98
lines changed

1 file changed

+109
-98
lines changed

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

Lines changed: 109 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -138,122 +138,133 @@ impl TargetInfo {
138138
rustc: &Rustc,
139139
kind: CompileKind,
140140
) -> CargoResult<TargetInfo> {
141-
let rustflags = env_args(
141+
let mut rustflags = env_args(
142142
config,
143143
requested_kinds,
144144
&rustc.host,
145145
None,
146146
kind,
147147
Flags::Rust,
148148
)?;
149-
let extra_fingerprint = kind.fingerprint_hash();
150-
let mut process = rustc.workspace_process();
151-
process
152-
.arg("-")
153-
.arg("--crate-name")
154-
.arg("___")
155-
.arg("--print=file-names")
156-
.args(&rustflags)
157-
.env_remove("RUSTC_LOG");
158-
159-
if let CompileKind::Target(target) = kind {
160-
process.arg("--target").arg(target.rustc_target());
161-
}
162-
163-
let crate_type_process = process.clone();
164-
const KNOWN_CRATE_TYPES: &[CrateType] = &[
165-
CrateType::Bin,
166-
CrateType::Rlib,
167-
CrateType::Dylib,
168-
CrateType::Cdylib,
169-
CrateType::Staticlib,
170-
CrateType::ProcMacro,
171-
];
172-
for crate_type in KNOWN_CRATE_TYPES.iter() {
173-
process.arg("--crate-type").arg(crate_type.as_str());
174-
}
175-
let supports_split_debuginfo = rustc
176-
.cached_output(
177-
process.clone().arg("-Csplit-debuginfo=packed"),
178-
extra_fingerprint,
179-
)
180-
.is_ok();
181-
182-
process.arg("--print=sysroot");
183-
process.arg("--print=cfg");
184-
185-
let (output, error) = rustc
186-
.cached_output(&process, extra_fingerprint)
187-
.with_context(|| "failed to run `rustc` to learn about target-specific information")?;
149+
for _ in 0..3 {
150+
let extra_fingerprint = kind.fingerprint_hash();
151+
let mut process = rustc.workspace_process();
152+
process
153+
.arg("-")
154+
.arg("--crate-name")
155+
.arg("___")
156+
.arg("--print=file-names")
157+
.args(&rustflags)
158+
.env_remove("RUSTC_LOG");
159+
160+
if let CompileKind::Target(target) = kind {
161+
process.arg("--target").arg(target.rustc_target());
162+
}
188163

189-
let mut lines = output.lines();
190-
let mut map = HashMap::new();
191-
for crate_type in KNOWN_CRATE_TYPES {
192-
let out = parse_crate_type(crate_type, &process, &output, &error, &mut lines)?;
193-
map.insert(crate_type.clone(), out);
194-
}
164+
let crate_type_process = process.clone();
165+
const KNOWN_CRATE_TYPES: &[CrateType] = &[
166+
CrateType::Bin,
167+
CrateType::Rlib,
168+
CrateType::Dylib,
169+
CrateType::Cdylib,
170+
CrateType::Staticlib,
171+
CrateType::ProcMacro,
172+
];
173+
for crate_type in KNOWN_CRATE_TYPES.iter() {
174+
process.arg("--crate-type").arg(crate_type.as_str());
175+
}
176+
let supports_split_debuginfo = rustc
177+
.cached_output(
178+
process.clone().arg("-Csplit-debuginfo=packed"),
179+
extra_fingerprint,
180+
)
181+
.is_ok();
182+
183+
process.arg("--print=sysroot");
184+
process.arg("--print=cfg");
185+
186+
let (output, error) = rustc
187+
.cached_output(&process, extra_fingerprint)
188+
.with_context(|| {
189+
"failed to run `rustc` to learn about target-specific information"
190+
})?;
191+
192+
let mut lines = output.lines();
193+
let mut map = HashMap::new();
194+
for crate_type in KNOWN_CRATE_TYPES {
195+
let out = parse_crate_type(crate_type, &process, &output, &error, &mut lines)?;
196+
map.insert(crate_type.clone(), out);
197+
}
195198

196-
let line = match lines.next() {
197-
Some(line) => line,
198-
None => anyhow::bail!(
199-
"output of --print=sysroot missing when learning about \
199+
let line = match lines.next() {
200+
Some(line) => line,
201+
None => anyhow::bail!(
202+
"output of --print=sysroot missing when learning about \
200203
target-specific information from rustc\n{}",
201-
output_err_info(&process, &output, &error)
202-
),
203-
};
204-
let sysroot = PathBuf::from(line);
205-
let sysroot_host_libdir = if cfg!(windows) {
206-
sysroot.join("bin")
207-
} else {
208-
sysroot.join("lib")
209-
};
210-
let mut sysroot_target_libdir = sysroot.clone();
211-
sysroot_target_libdir.push("lib");
212-
sysroot_target_libdir.push("rustlib");
213-
sysroot_target_libdir.push(match &kind {
214-
CompileKind::Host => rustc.host.as_str(),
215-
CompileKind::Target(target) => target.short_name(),
216-
});
217-
sysroot_target_libdir.push("lib");
218-
219-
let cfg = lines
220-
.map(|line| Ok(Cfg::from_str(line)?))
221-
.filter(TargetInfo::not_user_specific_cfg)
222-
.collect::<CargoResult<Vec<_>>>()
223-
.with_context(|| {
224-
format!(
225-
"failed to parse the cfg from `rustc --print=cfg`, got:\n{}",
226-
output
227-
)
228-
})?;
229-
230-
Ok(TargetInfo {
231-
crate_type_process,
232-
crate_types: RefCell::new(map),
233-
sysroot,
234-
sysroot_host_libdir,
235-
sysroot_target_libdir,
204+
output_err_info(&process, &output, &error)
205+
),
206+
};
207+
let sysroot = PathBuf::from(line);
208+
let sysroot_host_libdir = if cfg!(windows) {
209+
sysroot.join("bin")
210+
} else {
211+
sysroot.join("lib")
212+
};
213+
let mut sysroot_target_libdir = sysroot.clone();
214+
sysroot_target_libdir.push("lib");
215+
sysroot_target_libdir.push("rustlib");
216+
sysroot_target_libdir.push(match &kind {
217+
CompileKind::Host => rustc.host.as_str(),
218+
CompileKind::Target(target) => target.short_name(),
219+
});
220+
sysroot_target_libdir.push("lib");
221+
222+
let cfg = lines
223+
.map(|line| Ok(Cfg::from_str(line)?))
224+
.filter(TargetInfo::not_user_specific_cfg)
225+
.collect::<CargoResult<Vec<_>>>()
226+
.with_context(|| {
227+
format!(
228+
"failed to parse the cfg from `rustc --print=cfg`, got:\n{}",
229+
output
230+
)
231+
})?;
232+
236233
// recalculate `rustflags` from above now that we have `cfg`
237234
// information
238-
rustflags: env_args(
235+
let new_flags = env_args(
239236
config,
240237
requested_kinds,
241238
&rustc.host,
242239
Some(&cfg),
243240
kind,
244241
Flags::Rust,
245-
)?,
246-
rustdocflags: env_args(
247-
config,
248-
requested_kinds,
249-
&rustc.host,
250-
Some(&cfg),
251-
kind,
252-
Flags::Rustdoc,
253-
)?,
254-
cfg,
255-
supports_split_debuginfo,
256-
})
242+
)?;
243+
if new_flags != rustflags {
244+
rustflags = new_flags;
245+
continue;
246+
}
247+
248+
return Ok(TargetInfo {
249+
crate_type_process,
250+
crate_types: RefCell::new(map),
251+
sysroot,
252+
sysroot_host_libdir,
253+
sysroot_target_libdir,
254+
rustflags,
255+
rustdocflags: env_args(
256+
config,
257+
requested_kinds,
258+
&rustc.host,
259+
Some(&cfg),
260+
kind,
261+
Flags::Rustdoc,
262+
)?,
263+
cfg,
264+
supports_split_debuginfo,
265+
});
266+
}
267+
anyhow::bail!("diverging rustflags")
257268
}
258269

259270
fn not_user_specific_cfg(cfg: &CargoResult<Cfg>) -> bool {

0 commit comments

Comments
 (0)