11//! FIXME: write short doc here
22
33use std:: {
4+ env,
45 ffi:: OsStr ,
56 ops,
67 path:: { Path , PathBuf } ,
8+ process:: Command ,
79} ;
810
911use anyhow:: { Context , Result } ;
1012use cargo_metadata:: { BuildScript , CargoOpt , Message , MetadataCommand , PackageId } ;
1113use ra_arena:: { Arena , Idx } ;
1214use ra_db:: Edition ;
13- use ra_flycheck:: run_cargo;
1415use rustc_hash:: FxHashMap ;
1516use serde:: Deserialize ;
1617
@@ -163,7 +164,7 @@ impl CargoWorkspace {
163164 let mut out_dir_by_id = FxHashMap :: default ( ) ;
164165 let mut proc_macro_dylib_paths = FxHashMap :: default ( ) ;
165166 if cargo_features. load_out_dirs_from_check {
166- let resources = load_extern_resources ( cargo_toml, cargo_features) ;
167+ let resources = load_extern_resources ( cargo_toml, cargo_features) ? ;
167168 out_dir_by_id = resources. out_dirs ;
168169 proc_macro_dylib_paths = resources. proc_dylib_paths ;
169170 }
@@ -272,53 +273,51 @@ pub struct ExternResources {
272273 proc_dylib_paths : FxHashMap < PackageId , PathBuf > ,
273274}
274275
275- pub fn load_extern_resources ( cargo_toml : & Path , cargo_features : & CargoFeatures ) -> ExternResources {
276- let mut args: Vec < String > = vec ! [
277- "check" . to_string( ) ,
278- "--message-format=json" . to_string( ) ,
279- "--manifest-path" . to_string( ) ,
280- cargo_toml. display( ) . to_string( ) ,
281- ] ;
282-
276+ pub fn load_extern_resources (
277+ cargo_toml : & Path ,
278+ cargo_features : & CargoFeatures ,
279+ ) -> Result < ExternResources > {
280+ let mut cmd = Command :: new ( cargo_binary ( ) ) ;
281+ cmd. args ( & [ "check" , "--message-format=json" , "--manifest-path" ] ) . arg ( cargo_toml) ;
283282 if cargo_features. all_features {
284- args . push ( "--all-features" . to_string ( ) ) ;
283+ cmd . arg ( "--all-features" ) ;
285284 } else if cargo_features. no_default_features {
286285 // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
287286 // https://github.com/oli-obk/cargo_metadata/issues/79
288- args . push ( "--no-default-features" . to_string ( ) ) ;
287+ cmd . arg ( "--no-default-features" ) ;
289288 } else {
290- args . extend ( cargo_features. features . iter ( ) . cloned ( ) ) ;
289+ cmd . args ( & cargo_features. features ) ;
291290 }
292291
293- let mut acc = ExternResources :: default ( ) ;
294- let res = run_cargo ( & args, cargo_toml. parent ( ) , & mut |message| {
295- match message {
296- Message :: BuildScriptExecuted ( BuildScript { package_id, out_dir, .. } ) => {
297- acc. out_dirs . insert ( package_id, out_dir) ;
298- }
292+ let output = cmd. output ( ) ?;
293+
294+ let mut res = ExternResources :: default ( ) ;
295+
296+ let stdout = String :: from_utf8 ( output. stdout ) ?;
297+ for line in stdout. lines ( ) {
298+ if let Ok ( message) = serde_json:: from_str :: < cargo_metadata:: Message > ( & line) {
299+ match message {
300+ Message :: BuildScriptExecuted ( BuildScript { package_id, out_dir, .. } ) => {
301+ res. out_dirs . insert ( package_id, out_dir) ;
302+ }
299303
300- Message :: CompilerArtifact ( message) => {
301- if message. target . kind . contains ( & "proc-macro" . to_string ( ) ) {
302- let package_id = message. package_id ;
303- // Skip rmeta file
304- if let Some ( filename) =
305- message. filenames . iter ( ) . filter ( |name| is_dylib ( name) ) . next ( )
306- {
307- acc. proc_dylib_paths . insert ( package_id, filename. clone ( ) ) ;
304+ Message :: CompilerArtifact ( message) => {
305+ if message. target . kind . contains ( & "proc-macro" . to_string ( ) ) {
306+ let package_id = message. package_id ;
307+ // Skip rmeta file
308+ if let Some ( filename) =
309+ message. filenames . iter ( ) . filter ( |name| is_dylib ( name) ) . next ( )
310+ {
311+ res. proc_dylib_paths . insert ( package_id, filename. clone ( ) ) ;
312+ }
308313 }
309314 }
315+ Message :: CompilerMessage ( _) => ( ) ,
316+ Message :: Unknown => ( ) ,
310317 }
311- Message :: CompilerMessage ( _) => ( ) ,
312- Message :: Unknown => ( ) ,
313318 }
314- true
315- } ) ;
316-
317- if let Err ( err) = res {
318- log:: error!( "Failed to load outdirs: {:?}" , err) ;
319319 }
320-
321- acc
320+ Ok ( res)
322321}
323322
324323// FIXME: File a better way to know if it is a dylib
@@ -328,3 +327,7 @@ fn is_dylib(path: &Path) -> bool {
328327 Some ( ext) => matches ! ( ext. as_str( ) , "dll" | "dylib" | "so" ) ,
329328 }
330329}
330+
331+ fn cargo_binary ( ) -> String {
332+ env:: var ( "CARGO" ) . unwrap_or_else ( |_| "cargo" . to_string ( ) )
333+ }
0 commit comments