@@ -56,7 +56,7 @@ impl BuildScriptOutput {
56
56
}
57
57
58
58
impl WorkspaceBuildScripts {
59
- fn build_command ( config : & CargoConfig , current_dir : & path :: Path ) -> io:: Result < Command > {
59
+ fn build_command ( config : & CargoConfig ) -> io:: Result < Command > {
60
60
let mut cmd = match config. run_build_script_command . as_deref ( ) {
61
61
Some ( [ program, args @ ..] ) => {
62
62
let mut cmd = Command :: new ( program) ;
@@ -96,7 +96,6 @@ impl WorkspaceBuildScripts {
96
96
}
97
97
} ;
98
98
99
- cmd. current_dir ( current_dir) ;
100
99
cmd. envs ( & config. extra_env ) ;
101
100
if config. wrap_rustc_in_build_scripts {
102
101
// Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
@@ -127,15 +126,15 @@ impl WorkspaceBuildScripts {
127
126
}
128
127
. as_ref ( ) ;
129
128
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) {
131
130
Ok ( WorkspaceBuildScripts { error : Some ( error) , .. } )
132
131
if toolchain. as_ref ( ) . map_or ( false , |it| * it >= RUST_1_62 ) =>
133
132
{
134
133
// building build scripts failed, attempt to build with --keep-going so
135
134
// 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) ?;
137
136
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) ?;
139
138
res. error = Some ( error) ;
140
139
Ok ( res)
141
140
}
@@ -161,26 +160,34 @@ impl WorkspaceBuildScripts {
161
160
) )
162
161
}
163
162
} ;
164
- let cmd = Self :: build_command ( config, current_dir . as_path ( ) . as_ref ( ) ) ?;
163
+ let cmd = Self :: build_command ( config) ?;
165
164
// NB: Cargo.toml could have been modified between `cargo metadata` and
166
165
// `cargo check`. We shouldn't assume that package ids we see here are
167
166
// exactly those from `config`.
168
167
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 ( ) ;
169
171
let mut res: Vec < _ > = workspaces
170
172
. iter ( )
171
173
. enumerate ( )
172
174
. map ( |( idx, workspace) | {
173
175
let mut res = WorkspaceBuildScripts :: default ( ) ;
174
176
for package in workspace. packages ( ) {
175
177
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
+ }
177
183
}
178
184
res
179
185
} )
180
186
. collect ( ) ;
181
187
182
188
let errors = Self :: run_command (
183
189
cmd,
190
+ current_dir. as_path ( ) . as_ref ( ) ,
184
191
|package, cb| {
185
192
if let Some ( & ( package, workspace) ) = by_id. get ( package) {
186
193
cb ( & workspaces[ workspace] [ package] . name , & mut res[ workspace] . outputs [ package] ) ;
@@ -189,6 +196,11 @@ impl WorkspaceBuildScripts {
189
196
progress,
190
197
) ?;
191
198
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
+ } ) ;
192
204
193
205
if tracing:: enabled!( tracing:: Level :: INFO ) {
194
206
for ( idx, workspace) in workspaces. iter ( ) . enumerate ( ) {
@@ -211,6 +223,7 @@ impl WorkspaceBuildScripts {
211
223
fn run_per_ws (
212
224
cmd : Command ,
213
225
workspace : & CargoWorkspace ,
226
+ current_dir : & path:: Path ,
214
227
progress : & dyn Fn ( String ) ,
215
228
) -> io:: Result < WorkspaceBuildScripts > {
216
229
let mut res = WorkspaceBuildScripts :: default ( ) ;
@@ -226,6 +239,7 @@ impl WorkspaceBuildScripts {
226
239
227
240
res. error = Self :: run_command (
228
241
cmd,
242
+ current_dir,
229
243
|package, cb| {
230
244
if let Some ( & package) = by_id. get ( package) {
231
245
cb ( & workspace[ package] . name , & mut outputs[ package] ) ;
@@ -251,7 +265,8 @@ impl WorkspaceBuildScripts {
251
265
}
252
266
253
267
fn run_command (
254
- cmd : Command ,
268
+ mut cmd : Command ,
269
+ current_dir : & path:: Path ,
255
270
// ideally this would be something like:
256
271
// with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)),
257
272
// but owned trait objects aren't a thing
@@ -265,7 +280,8 @@ impl WorkspaceBuildScripts {
265
280
e. push ( '\n' ) ;
266
281
} ;
267
282
268
- tracing:: info!( "Running build scripts: {:?}" , cmd) ;
283
+ tracing:: info!( "Running build scripts in {}: {:?}" , current_dir. display( ) , cmd) ;
284
+ cmd. current_dir ( current_dir) ;
269
285
let output = stdx:: process:: spawn_with_streaming_output (
270
286
cmd,
271
287
& mut |line| {
0 commit comments