@@ -8,17 +8,15 @@ use cargo::core::{Package, PackageId, Source, SourceId, Workspace};
8
8
use cargo:: sources:: RegistrySource ;
9
9
use curl:: easy:: Easy ;
10
10
use log:: debug;
11
- use rand:: Rng ;
12
11
use rustc_session:: getopts;
13
12
use serde:: Deserialize ;
14
13
use std:: collections:: HashSet ;
15
14
use std:: {
16
- env,
17
- fs:: File ,
18
- io:: BufReader ,
15
+ env, io,
19
16
io:: Write ,
20
17
path:: { Path , PathBuf } ,
21
18
process:: { Command , Stdio } ,
19
+ sync:: { Arc , RwLock } ,
22
20
} ;
23
21
24
22
pub type Result < T > = cargo:: util:: CargoResult < T > ;
@@ -481,13 +479,15 @@ impl<'a> WorkInfo<'a> {
481
479
// we need the build plan to find our build artifacts
482
480
opts. build_config . build_plan = true ;
483
481
484
- if let Some ( target) = matches. opt_str ( "target" ) {
485
- let target = cargo:: core:: compiler:: CompileTarget :: new ( & target) ;
486
- if let Ok ( target) = target {
487
- let kind = cargo:: core:: compiler:: CompileKind :: Target ( target) ;
488
- opts. build_config . requested_kind = kind;
489
- }
490
- }
482
+ let compile_kind = if let Some ( target) = matches. opt_str ( "target" ) {
483
+ let target = cargo:: core:: compiler:: CompileTarget :: new ( & target) ?;
484
+
485
+ let kind = cargo:: core:: compiler:: CompileKind :: Target ( target) ;
486
+ opts. build_config . requested_kinds = vec ! [ kind] ;
487
+ kind
488
+ } else {
489
+ cargo:: core:: compiler:: CompileKind :: Host
490
+ } ;
491
491
492
492
if let Some ( s) = matches. opt_str ( "features" ) {
493
493
opts. features = s. split ( ' ' ) . map ( str:: to_owned) . collect ( ) ;
@@ -501,36 +501,35 @@ impl<'a> WorkInfo<'a> {
501
501
format ! ( "-C metadata={}" , if current { "new" } else { "old" } ) ,
502
502
) ;
503
503
504
- let mut outdir = env:: temp_dir ( ) ;
505
- // The filename is randomized to avoid clashes when multiple cargo-semver instances are running.
506
- outdir. push ( & format ! (
507
- "cargo_semver_{}_{}_{}" ,
508
- name,
509
- current,
510
- rand:: thread_rng( ) . gen :: <u32 >( )
511
- ) ) ;
504
+ // Capture build plan from a separate Cargo invocation
505
+ let output = VecWrite ( Arc :: new ( RwLock :: new ( Vec :: new ( ) ) ) ) ;
506
+
507
+ let mut file_write = cargo:: core:: Shell :: from_write ( Box :: new ( output. clone ( ) ) ) ;
508
+ file_write. set_verbosity ( cargo:: core:: Verbosity :: Quiet ) ;
512
509
513
- // redirection gang
514
- let outfile = File :: create ( & outdir) ?;
515
- let old_stdio = std:: io:: set_print ( Some ( Box :: new ( outfile) ) ) ;
510
+ let old_shell = std:: mem:: replace ( & mut * config. shell ( ) , file_write) ;
516
511
517
- let _ = cargo:: ops:: compile ( & self . workspace , & opts) ?;
512
+ cargo:: ops:: compile ( & self . workspace , & opts) ?;
518
513
519
- std:: io:: set_print ( old_stdio) ;
514
+ let _ = std:: mem:: replace ( & mut * config. shell ( ) , old_shell) ;
515
+ let plan_output = output. read ( ) ?;
520
516
521
517
// actually compile things now
522
518
opts. build_config . build_plan = false ;
523
519
524
520
let compilation = cargo:: ops:: compile ( & self . workspace , & opts) ?;
525
521
env:: remove_var ( "RUSTFLAGS" ) ;
526
522
527
- let build_plan: BuildPlan = serde_json:: from_reader ( BufReader :: new ( File :: open ( & outdir) ?) ) ?;
523
+ let build_plan: BuildPlan = serde_json:: from_slice ( & plan_output)
524
+ . map_err ( |_| anyhow:: anyhow!( "Can't read build plan" ) ) ?;
528
525
529
526
// TODO: handle multiple outputs gracefully
530
527
for i in & build_plan. invocations {
531
528
if let Some ( kind) = i. target_kind . get ( 0 ) {
532
529
if kind. contains ( "lib" ) && i. package_name == name {
533
- return Ok ( ( i. outputs [ 0 ] . clone ( ) , compilation. deps_output ) ) ;
530
+ let deps_output = & compilation. deps_output [ & compile_kind] ;
531
+
532
+ return Ok ( ( i. outputs [ 0 ] . clone ( ) , deps_output. clone ( ) ) ) ;
534
533
}
535
534
}
536
535
}
@@ -565,3 +564,30 @@ pub fn find_on_crates_io(crate_name: &str) -> Result<crates_io::Crate> {
565
564
} )
566
565
} )
567
566
}
567
+
568
+ /// Thread-safe byte buffer that implements `io::Write`.
569
+ #[ derive( Clone ) ]
570
+ struct VecWrite ( Arc < RwLock < Vec < u8 > > > ) ;
571
+
572
+ impl VecWrite {
573
+ pub fn read ( & self ) -> io:: Result < std:: sync:: RwLockReadGuard < ' _ , Vec < u8 > > > {
574
+ self . 0
575
+ . read ( )
576
+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "lock poison" ) )
577
+ }
578
+ pub fn write ( & self ) -> io:: Result < std:: sync:: RwLockWriteGuard < ' _ , Vec < u8 > > > {
579
+ self . 0
580
+ . write ( )
581
+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "lock poison" ) )
582
+ }
583
+ }
584
+
585
+ impl io:: Write for VecWrite {
586
+ fn write ( & mut self , data : & [ u8 ] ) -> io:: Result < usize > {
587
+ let mut lock = Self :: write ( self ) ?;
588
+ io:: Write :: write ( & mut * lock, data)
589
+ }
590
+ fn flush ( & mut self ) -> io:: Result < ( ) > {
591
+ Ok ( ( ) )
592
+ }
593
+ }
0 commit comments