@@ -8,17 +8,15 @@ use cargo::core::{Package, PackageId, Source, SourceId, Workspace};
88use cargo:: sources:: RegistrySource ;
99use curl:: easy:: Easy ;
1010use log:: debug;
11- use rand:: Rng ;
1211use rustc_session:: getopts;
1312use serde:: Deserialize ;
1413use std:: collections:: HashSet ;
1514use std:: {
16- env,
17- fs:: File ,
18- io:: BufReader ,
15+ env, io,
1916 io:: Write ,
2017 path:: { Path , PathBuf } ,
2118 process:: { Command , Stdio } ,
19+ sync:: { Arc , RwLock } ,
2220} ;
2321
2422pub type Result < T > = cargo:: util:: CargoResult < T > ;
@@ -481,13 +479,15 @@ impl<'a> WorkInfo<'a> {
481479 // we need the build plan to find our build artifacts
482480 opts. build_config . build_plan = true ;
483481
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+ } ;
491491
492492 if let Some ( s) = matches. opt_str ( "features" ) {
493493 opts. features = s. split ( ' ' ) . map ( str:: to_owned) . collect ( ) ;
@@ -501,36 +501,35 @@ impl<'a> WorkInfo<'a> {
501501 format ! ( "-C metadata={}" , if current { "new" } else { "old" } ) ,
502502 ) ;
503503
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 ) ;
512509
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) ;
516511
517- let _ = cargo:: ops:: compile ( & self . workspace , & opts) ?;
512+ cargo:: ops:: compile ( & self . workspace , & opts) ?;
518513
519- std:: io:: set_print ( old_stdio) ;
514+ let _ = std:: mem:: replace ( & mut * config. shell ( ) , old_shell) ;
515+ let plan_output = output. read ( ) ?;
520516
521517 // actually compile things now
522518 opts. build_config . build_plan = false ;
523519
524520 let compilation = cargo:: ops:: compile ( & self . workspace , & opts) ?;
525521 env:: remove_var ( "RUSTFLAGS" ) ;
526522
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" ) ) ?;
528525
529526 // TODO: handle multiple outputs gracefully
530527 for i in & build_plan. invocations {
531528 if let Some ( kind) = i. target_kind . get ( 0 ) {
532529 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 ( ) ) ) ;
534533 }
535534 }
536535 }
@@ -565,3 +564,30 @@ pub fn find_on_crates_io(crate_name: &str) -> Result<crates_io::Crate> {
565564 } )
566565 } )
567566}
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