8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use cargo:: core:: { PackageId , Shell , Target , Workspace , Verbosity } ;
11
+ use cargo:: core:: { PackageId , Shell , Target , TargetKind , Workspace , Verbosity } ;
12
12
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 } ;
15
14
use serde_json;
16
15
17
16
use data:: Analysis ;
@@ -296,38 +295,36 @@ impl Executor for RlsExecutor {
296
295
}
297
296
}
298
297
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) ) ;
301
310
cmd. env ( :: RUSTC_SHIM_ENV_VAR_NAME , "1" ) ;
302
311
303
312
// We only want to intercept rustc call targeting current crate to cache
304
313
// args/envs generated by cargo so we can run only rustc later ourselves
305
314
// 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 ;
307
316
if !self . is_primary_crate ( id) || is_build_script {
308
317
let mut cmd = Command :: new ( & env:: var ( "RUSTC" ) . unwrap_or ( "rustc" . to_owned ( ) ) ) ;
309
318
let build_script_notice = if is_build_script { " (build script)" } else { "" } ;
310
319
trace ! ( "rustc not intercepted - {}{}" , id. name( ) , build_script_notice) ;
311
320
321
+ // Recreate the command, minus -Zsave-analysis.
312
322
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 {
329
- return cargo_cmd. exec ( ) ;
323
+ let args: Vec < _ > = cmd. get_args ( ) . iter ( ) . cloned ( )
324
+ . filter ( |x| x != "Zsave-analysis" ) . collect ( ) ;
325
+ cmd. args_replace ( & args) ;
330
326
}
327
+ return cmd. exec ( ) ;
331
328
}
332
329
333
330
trace ! ( "rustc intercepted - args: {:?} envs: {:?}" , cargo_args, cargo_cmd. get_envs( ) ) ;
@@ -370,43 +367,28 @@ impl Executor for RlsExecutor {
370
367
// so the dep-info is ready by the time we return from this callback.
371
368
// NB: In `workspace_mode` regular compilation is performed here (and we don't
372
369
// 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
- }
370
+ let modified = args. iter ( )
371
+ . filter ( |a| * a != "-Zsave-analysis" )
372
+ . map ( |a| {
373
+ // Emitting only dep-info is possible only for final crate type, as
374
+ // as others may emit required metadata for dependent crate types
375
+ if a. starts_with ( "--emit" ) && is_final_crate_type && !self . workspace_mode {
376
+ "--emit=dep-info"
377
+ } else { a }
378
+ } )
379
+ . collect :: < Vec < _ > > ( ) ;
380
+ cmd. args_replace ( & modified) ;
388
381
}
389
382
390
383
// Cache executed command for the build plan
391
384
{
392
385
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) ;
386
+ cx. build_plan . cache_compiler_job ( id, target, & cmd) ;
406
387
}
407
388
408
389
// Prepare modified cargo-generated args/envs for future rustc calls
409
- args. insert ( 0 , rustc_exe) ;
390
+ let rustc = cargo_cmd. get_program ( ) . to_owned ( ) . into_string ( ) . unwrap ( ) ;
391
+ args. insert ( 0 , rustc) ;
410
392
let envs = cargo_cmd. get_envs ( ) . clone ( ) ;
411
393
412
394
if self . workspace_mode {
@@ -426,7 +408,7 @@ impl Executor for RlsExecutor {
426
408
_ => { }
427
409
}
428
410
} else {
429
- cmd. status ( ) . expect ( "Couldn't execute rustc" ) ;
411
+ cmd. exec ( ) ? ;
430
412
}
431
413
432
414
// Finally, store the modified cargo-generated args/envs for future rustc calls
0 commit comments