@@ -56,7 +56,7 @@ impl BuildScriptOutput {
5656}
5757
5858impl WorkspaceBuildScripts {
59- fn build_command ( config : & CargoConfig , current_dir : & path :: Path ) -> io:: Result < Command > {
59+ fn build_command ( config : & CargoConfig ) -> io:: Result < Command > {
6060 let mut cmd = match config. run_build_script_command . as_deref ( ) {
6161 Some ( [ program, args @ ..] ) => {
6262 let mut cmd = Command :: new ( program) ;
@@ -96,7 +96,6 @@ impl WorkspaceBuildScripts {
9696 }
9797 } ;
9898
99- cmd. current_dir ( current_dir) ;
10099 cmd. envs ( & config. extra_env ) ;
101100 if config. wrap_rustc_in_build_scripts {
102101 // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
@@ -127,15 +126,15 @@ impl WorkspaceBuildScripts {
127126 }
128127 . as_ref ( ) ;
129128
130- match Self :: run_per_ws ( Self :: build_command ( config, current_dir ) ?, workspace, progress) {
129+ match Self :: run_per_ws ( Self :: build_command ( config) ?, workspace, current_dir , progress) {
131130 Ok ( WorkspaceBuildScripts { error : Some ( error) , .. } )
132131 if toolchain. as_ref ( ) . map_or ( false , |it| * it >= RUST_1_62 ) =>
133132 {
134133 // building build scripts failed, attempt to build with --keep-going so
135134 // that we potentially get more build data
136- let mut cmd = Self :: build_command ( config, current_dir ) ?;
135+ let mut cmd = Self :: build_command ( config) ?;
137136 cmd. args ( & [ "-Z" , "unstable-options" , "--keep-going" ] ) . env ( "RUSTC_BOOTSTRAP" , "1" ) ;
138- let mut res = Self :: run_per_ws ( cmd, workspace, progress) ?;
137+ let mut res = Self :: run_per_ws ( cmd, workspace, current_dir , progress) ?;
139138 res. error = Some ( error) ;
140139 Ok ( res)
141140 }
@@ -161,26 +160,34 @@ impl WorkspaceBuildScripts {
161160 ) )
162161 }
163162 } ;
164- let cmd = Self :: build_command ( config, current_dir . as_path ( ) . as_ref ( ) ) ?;
163+ let cmd = Self :: build_command ( config) ?;
165164 // NB: Cargo.toml could have been modified between `cargo metadata` and
166165 // `cargo check`. We shouldn't assume that package ids we see here are
167166 // exactly those from `config`.
168167 let mut by_id = FxHashMap :: default ( ) ;
168+ // some workspaces might depend on the same crates, so we need to duplicate the outputs
169+ // to those collisions
170+ let mut collisions = Vec :: new ( ) ;
169171 let mut res: Vec < _ > = workspaces
170172 . iter ( )
171173 . enumerate ( )
172174 . map ( |( idx, workspace) | {
173175 let mut res = WorkspaceBuildScripts :: default ( ) ;
174176 for package in workspace. packages ( ) {
175177 res. outputs . insert ( package, BuildScriptOutput :: default ( ) ) ;
176- by_id. insert ( workspace[ package] . id . clone ( ) , ( package, idx) ) ;
178+ if by_id. contains_key ( & workspace[ package] . id ) {
179+ collisions. push ( ( & workspace[ package] . id , idx, package) ) ;
180+ } else {
181+ by_id. insert ( workspace[ package] . id . clone ( ) , ( package, idx) ) ;
182+ }
177183 }
178184 res
179185 } )
180186 . collect ( ) ;
181187
182188 let errors = Self :: run_command (
183189 cmd,
190+ current_dir. as_path ( ) . as_ref ( ) ,
184191 |package, cb| {
185192 if let Some ( & ( package, workspace) ) = by_id. get ( package) {
186193 cb ( & workspaces[ workspace] [ package] . name , & mut res[ workspace] . outputs [ package] ) ;
@@ -189,6 +196,11 @@ impl WorkspaceBuildScripts {
189196 progress,
190197 ) ?;
191198 res. iter_mut ( ) . for_each ( |it| it. error = errors. clone ( ) ) ;
199+ collisions. into_iter ( ) . for_each ( |( id, workspace, package) | {
200+ if let Some ( & ( p, w) ) = by_id. get ( id) {
201+ res[ workspace] . outputs [ package] = res[ w] . outputs [ p] . clone ( ) ;
202+ }
203+ } ) ;
192204
193205 if tracing:: enabled!( tracing:: Level :: INFO ) {
194206 for ( idx, workspace) in workspaces. iter ( ) . enumerate ( ) {
@@ -211,6 +223,7 @@ impl WorkspaceBuildScripts {
211223 fn run_per_ws (
212224 cmd : Command ,
213225 workspace : & CargoWorkspace ,
226+ current_dir : & path:: Path ,
214227 progress : & dyn Fn ( String ) ,
215228 ) -> io:: Result < WorkspaceBuildScripts > {
216229 let mut res = WorkspaceBuildScripts :: default ( ) ;
@@ -226,6 +239,7 @@ impl WorkspaceBuildScripts {
226239
227240 res. error = Self :: run_command (
228241 cmd,
242+ current_dir,
229243 |package, cb| {
230244 if let Some ( & package) = by_id. get ( package) {
231245 cb ( & workspace[ package] . name , & mut outputs[ package] ) ;
@@ -251,7 +265,8 @@ impl WorkspaceBuildScripts {
251265 }
252266
253267 fn run_command (
254- cmd : Command ,
268+ mut cmd : Command ,
269+ current_dir : & path:: Path ,
255270 // ideally this would be something like:
256271 // with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)),
257272 // but owned trait objects aren't a thing
@@ -265,7 +280,8 @@ impl WorkspaceBuildScripts {
265280 e. push ( '\n' ) ;
266281 } ;
267282
268- tracing:: info!( "Running build scripts: {:?}" , cmd) ;
283+ tracing:: info!( "Running build scripts in {}: {:?}" , current_dir. display( ) , cmd) ;
284+ cmd. current_dir ( current_dir) ;
269285 let output = stdx:: process:: spawn_with_streaming_output (
270286 cmd,
271287 & mut |line| {
0 commit comments