@@ -8,6 +8,7 @@ use scarb_ui::args::FeaturesSpec;
8
8
use scarb_ui:: components:: Status ;
9
9
use scarb_ui:: HumanDuration ;
10
10
use smol_str:: { SmolStr , ToSmolStr } ;
11
+ use std:: collections:: HashSet ;
11
12
use std:: thread;
12
13
13
14
use crate :: compiler:: db:: { build_scarb_root_database, has_starknet_plugin, ScarbDatabase } ;
@@ -97,12 +98,12 @@ impl CompileOpts {
97
98
98
99
#[ tracing:: instrument( skip_all, level = "debug" ) ]
99
100
pub fn compile ( packages : Vec < PackageId > , opts : CompileOpts , ws : & Workspace < ' _ > ) -> Result < ( ) > {
100
- process ( packages, opts, ws, compile_unit , None )
101
+ process ( packages, opts, ws, compile_units , None )
101
102
}
102
103
103
104
#[ tracing:: instrument( skip_all, level = "debug" ) ]
104
105
pub fn check ( packages : Vec < PackageId > , opts : CompileOpts , ws : & Workspace < ' _ > ) -> Result < ( ) > {
105
- process ( packages, opts, ws, check_unit , Some ( "checking" ) )
106
+ process ( packages, opts, ws, check_units , Some ( "checking" ) )
106
107
}
107
108
108
109
#[ tracing:: instrument( skip_all, level = "debug" ) ]
@@ -114,7 +115,7 @@ fn process<F>(
114
115
operation_type : Option < & str > ,
115
116
) -> Result < ( ) >
116
117
where
117
- F : FnMut ( CompilationUnit , & Workspace < ' _ > ) -> Result < ( ) > ,
118
+ F : FnMut ( Vec < CompilationUnit > , & Workspace < ' _ > ) -> Result < ( ) > ,
118
119
{
119
120
let resolve = ops:: resolve_workspace ( ws) ?;
120
121
let packages_to_process = ws
@@ -155,9 +156,7 @@ where
155
156
} )
156
157
. collect :: < Vec < _ > > ( ) ;
157
158
158
- for unit in compilation_units {
159
- operation ( unit, ws) ?;
160
- }
159
+ operation ( compilation_units, ws) ?;
161
160
162
161
let elapsed_time = HumanDuration ( ws. config ( ) . elapsed_time ( ) ) ;
163
162
let profile = ws. current_profile ( ) ?;
@@ -174,6 +173,13 @@ where
174
173
175
174
/// Run compiler in a new thread.
176
175
/// The stack size of created threads can be altered with `RUST_MIN_STACK` env variable.
176
+ pub fn compile_units ( units : Vec < CompilationUnit > , ws : & Workspace < ' _ > ) -> Result < ( ) > {
177
+ for unit in units {
178
+ compile_unit ( unit, ws) ?;
179
+ }
180
+ Ok ( ( ) )
181
+ }
182
+
177
183
pub fn compile_unit ( unit : CompilationUnit , ws : & Workspace < ' _ > ) -> Result < ( ) > {
178
184
thread:: scope ( |s| {
179
185
thread:: Builder :: new ( )
@@ -217,6 +223,42 @@ fn compile_unit_inner(unit: CompilationUnit, ws: &Workspace<'_>) -> Result<()> {
217
223
} )
218
224
}
219
225
226
+ fn check_units ( units : Vec < CompilationUnit > , ws : & Workspace < ' _ > ) -> Result < ( ) > {
227
+ // Select proc macro units that need to be compiled for Cairo compilation units.
228
+ let required_plugins = units
229
+ . iter ( )
230
+ . flat_map ( |unit| match unit {
231
+ CompilationUnit :: Cairo ( unit) => unit
232
+ . cairo_plugins
233
+ . iter ( )
234
+ . map ( |p| p. package . id )
235
+ . collect_vec ( ) ,
236
+ _ => Vec :: new ( ) ,
237
+ } )
238
+ . collect :: < HashSet < PackageId > > ( ) ;
239
+
240
+ // We guarantee that proc-macro units are always processed first,
241
+ // so that all required plugins are compiled before we start checking Cairo units.
242
+ let units = units. into_iter ( ) . sorted_by_key ( |unit| {
243
+ if matches ! ( unit, CompilationUnit :: ProcMacro ( _) ) {
244
+ 0
245
+ } else {
246
+ 1
247
+ }
248
+ } ) ;
249
+
250
+ for unit in units {
251
+ if matches ! ( unit, CompilationUnit :: ProcMacro ( _) )
252
+ && required_plugins. contains ( & unit. main_package_id ( ) )
253
+ {
254
+ compile_unit ( unit, ws) ?;
255
+ } else {
256
+ check_unit ( unit, ws) ?;
257
+ }
258
+ }
259
+ Ok ( ( ) )
260
+ }
261
+
220
262
fn check_unit ( unit : CompilationUnit , ws : & Workspace < ' _ > ) -> Result < ( ) > {
221
263
let package_name = unit. main_package_id ( ) . name . clone ( ) ;
222
264
0 commit comments