Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 7f87fb4

Browse files
authored
Merge pull request #456 from Xanewok/simplify-process-builder
Simplify `ProcessBuilder` modification
2 parents 303671e + 68ffac0 commit 7f87fb4

File tree

1 file changed

+41
-53
lines changed

1 file changed

+41
-53
lines changed

src/build/cargo.rs

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use cargo::core::{PackageId, Shell, Target, Workspace, Verbosity};
11+
use cargo::core::{PackageId, Shell, Target, TargetKind, Workspace, Verbosity};
1212
use cargo::ops::{compile_with_exec, Executor, Context, Packages, CompileOptions, CompileMode, CompileFilter, Unit};
13-
use cargo::util::{Config as CargoConfig, process_builder, ProcessBuilder, homedir, important_paths, ConfigValue, CargoResult};
14-
use cargo::util::errors::{CargoErrorKind, process_error};
13+
use cargo::util::{Config as CargoConfig, ProcessBuilder, homedir, important_paths, ConfigValue, CargoResult};
1514
use serde_json;
1615

1716
use data::Analysis;
@@ -296,38 +295,42 @@ impl Executor for RlsExecutor {
296295
}
297296
}
298297

299-
let rustc_exe = env::var("RUSTC").unwrap_or(env::args().next().unwrap());
300-
let mut cmd = Command::new(&rustc_exe);
298+
// Prepare our own call to `rustc` as follows:
299+
// 1. Use $RUSTC wrapper if specified, otherwise use RLS executable
300+
// as an rustc shim (needed to distribute via the stable channel)
301+
// 2. For non-primary packages or build scripts, execute the call
302+
// 3. Otherwise, we'll want to use the compilation to drive the analysis:
303+
// i. Modify arguments to account for the RLS settings (e.g.
304+
// compiling under cfg(test) mode or passing a custom sysroot)
305+
// ii. Execute the call and store the final args/envs to be used for
306+
// later in-process execution of the compiler
307+
let mut cmd = cargo_cmd.clone();
308+
let rls_executable = env::args().next().unwrap();
309+
cmd.program(env::var("RUSTC").unwrap_or(rls_executable));
301310
cmd.env(::RUSTC_SHIM_ENV_VAR_NAME, "1");
302311

303312
// We only want to intercept rustc call targeting current crate to cache
304313
// args/envs generated by cargo so we can run only rustc later ourselves
305314
// Currently we don't cache nor modify build script args
306-
let is_build_script = crate_name == "build_script_build";
315+
let is_build_script = *target.kind() == TargetKind::CustomBuild;
307316
if !self.is_primary_crate(id) || is_build_script {
308-
let mut cmd = Command::new(&env::var("RUSTC").unwrap_or("rustc".to_owned()));
309317
let build_script_notice = if is_build_script {" (build script)"} else {""};
310318
trace!("rustc not intercepted - {}{}", id.name(), build_script_notice);
311319

320+
// Recreate the original command, minus -Zsave-analysis. Since the
321+
// shim sets it internally, be sure not to use it.
312322
if ::CRATE_BLACKLIST.contains(&&*crate_name) {
313-
// Recreate the command, minus -Zsave-analysis.
314-
for a in cargo_args {
315-
if a != "-Zsave-analysis" {
316-
cmd.arg(a);
317-
}
318-
}
319-
cmd.envs(cargo_cmd.get_envs().iter().filter_map(|(k, v)| v.as_ref().map(|v| (k, v))));
320-
if let Some(cwd) = cargo_cmd.get_cwd() {
321-
cmd.current_dir(cwd);
322-
}
323-
return match cmd.status() {
324-
Ok(ref e) if e.success() => Ok(()),
325-
_ => Err(CargoErrorKind::ProcessErrorKind(process_error(
326-
"process didn't exit successfully", None, None)).into()),
327-
};
328-
} else {
323+
let mut cargo_cmd = cargo_cmd.clone();
324+
let args: Vec<_> = cargo_cmd.get_args().iter().cloned()
325+
.filter(|x| x != "Zsave-analysis").collect();
326+
cargo_cmd.args_replace(&args);
327+
329328
return cargo_cmd.exec();
330329
}
330+
// TODO: Make sure we don't pass any unstable options (incl. -Zsave-analysis)
331+
// to the shim. For stable toolchains it won't accept those as arguments,
332+
// but rather it sets them internally instead to work around that
333+
return cmd.exec();
331334
}
332335

333336
trace!("rustc intercepted - args: {:?} envs: {:?}", cargo_args, cargo_cmd.get_envs());
@@ -370,43 +373,28 @@ impl Executor for RlsExecutor {
370373
// so the dep-info is ready by the time we return from this callback.
371374
// NB: In `workspace_mode` regular compilation is performed here (and we don't
372375
// only calculate dep-info) so it should fix the problem mentioned above.
373-
// Since ProcessBuilder doesn't allow to modify args, we need to create
374-
// our own command here from scratch here.
375-
for a in &args {
376-
// Emitting only dep-info is possible only for final crate type, as
377-
// as others may emit required metadata for dependent crate types
378-
if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode {
379-
cmd.arg("--emit=dep-info");
380-
} else if a != "-Zsave-analysis" {
381-
cmd.arg(a);
382-
}
383-
}
384-
cmd.envs(cargo_cmd.get_envs().iter().filter_map(|(k, v)| v.as_ref().map(|v| (k, v))));
385-
if let Some(cwd) = cargo_cmd.get_cwd() {
386-
cmd.current_dir(cwd);
387-
}
376+
let modified = args.iter()
377+
.filter(|a| *a != "-Zsave-analysis")
378+
.map(|a| {
379+
// Emitting only dep-info is possible only for final crate type, as
380+
// as others may emit required metadata for dependent crate types
381+
if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode {
382+
"--emit=dep-info"
383+
} else { a }
384+
})
385+
.collect::<Vec<_>>();
386+
cmd.args_replace(&modified);
388387
}
389388

390389
// Cache executed command for the build plan
391390
{
392391
let mut cx = self.compilation_cx.lock().unwrap();
393-
394-
let mut store_cmd = process_builder::process(&rustc_exe);
395-
store_cmd.args(&args.iter().map(OsString::from).collect::<Vec<_>>());
396-
for (k, v) in cargo_cmd.get_envs().clone() {
397-
if let Some(v) = v {
398-
store_cmd.env(&k, v);
399-
}
400-
}
401-
if let Some(cwd) = cargo_cmd.get_cwd() {
402-
cmd.current_dir(cwd);
403-
}
404-
405-
cx.build_plan.cache_compiler_job(id, target, &store_cmd);
392+
cx.build_plan.cache_compiler_job(id, target, &cmd);
406393
}
407394

408395
// Prepare modified cargo-generated args/envs for future rustc calls
409-
args.insert(0, rustc_exe);
396+
let rustc = cargo_cmd.get_program().to_owned().into_string().unwrap();
397+
args.insert(0, rustc);
410398
let envs = cargo_cmd.get_envs().clone();
411399

412400
if self.workspace_mode {
@@ -426,7 +414,7 @@ impl Executor for RlsExecutor {
426414
_ => {}
427415
}
428416
} else {
429-
cmd.status().expect("Couldn't execute rustc");
417+
cmd.exec()?;
430418
}
431419

432420
// Finally, store the modified cargo-generated args/envs for future rustc calls

0 commit comments

Comments
 (0)