@@ -3,7 +3,7 @@ use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbos
33use serde:: { Deserialize , Serialize } ;
44
55/// Global options.
6- #[ derive( Clone , Copy , Debug , Default , Serialize , Deserialize , Parser ) ]
6+ #[ derive( Clone , Debug , Default , Serialize , Deserialize , Parser ) ]
77pub struct GlobalOpts {
88 /// Verbosity level of the log messages.
99 ///
@@ -16,39 +16,47 @@ pub struct GlobalOpts {
1616 /// - 3 (-vvv): Print execution traces for failing tests.
1717 /// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests.
1818 /// - 5 (-vvvvv): Print execution and setup traces for all tests.
19- #[ clap ( short , long , global = true , verbatim_doc_comment, conflicts_with = "quiet" , action = ArgAction :: Count , help_heading = "Display options" ) ]
20- pub verbosity : Verbosity ,
19+ #[ arg ( help_heading = "Display options" , global = true , short , long , verbatim_doc_comment, conflicts_with = "quiet" , action = ArgAction :: Count ) ]
20+ verbosity : Verbosity ,
2121
2222 /// Do not print log messages.
23- #[ clap ( short , long , global = true , alias = "silent" , help_heading = "Display options " ) ]
23+ #[ arg ( help_heading = "Display options" , global = true , short , long , alias = "silent " ) ]
2424 quiet : bool ,
2525
2626 /// Format log messages as JSON.
27- #[ clap(
28- long,
29- global = true ,
30- alias = "format-json" ,
31- conflicts_with_all = & [ "quiet" , "color" ] ,
32- help_heading = "Display options"
33- ) ]
27+ #[ arg( help_heading = "Display options" , global = true , long, alias = "format-json" , conflicts_with_all = & [ "quiet" , "color" ] ) ]
3428 json : bool ,
3529
3630 /// The color of the log messages.
37- #[ clap ( long , global = true , value_enum , help_heading = "Display options" ) ]
31+ #[ arg ( help_heading = "Display options" , global = true , long , value_enum ) ]
3832 color : Option < ColorChoice > ,
33+
34+ /// Number of threads to use. Specifying 0 defaults to the number of logical cores.
35+ #[ arg( global = true , long, short = 'j' , visible_alias = "jobs" ) ]
36+ threads : Option < usize > ,
3937}
4038
4139impl GlobalOpts {
4240 /// Initialize the global options.
43- pub fn init ( self ) -> eyre:: Result < ( ) > {
41+ pub fn init ( & self ) -> eyre:: Result < ( ) > {
4442 // Set the global shell.
4543 self . shell ( ) . set ( ) ;
4644
45+ // Initialize the thread pool only if `threads` was requested to avoid unnecessary overhead.
46+ if self . threads . is_some ( ) {
47+ self . force_init_thread_pool ( ) ?;
48+ }
49+
4750 Ok ( ( ) )
4851 }
4952
53+ /// Initialize the global thread pool.
54+ pub fn force_init_thread_pool ( & self ) -> eyre:: Result < ( ) > {
55+ init_thread_pool ( self . threads . unwrap_or ( 0 ) )
56+ }
57+
5058 /// Create a new shell instance.
51- pub fn shell ( self ) -> Shell {
59+ pub fn shell ( & self ) -> Shell {
5260 let mode = match self . quiet {
5361 true => OutputMode :: Quiet ,
5462 false => OutputMode :: Normal ,
@@ -62,3 +70,12 @@ impl GlobalOpts {
6270 Shell :: new_with ( format, mode, color, self . verbosity )
6371 }
6472}
73+
74+ /// Initialize the global thread pool.
75+ pub fn init_thread_pool ( threads : usize ) -> eyre:: Result < ( ) > {
76+ rayon:: ThreadPoolBuilder :: new ( )
77+ . thread_name ( |i| format ! ( "foundry-{i}" ) )
78+ . num_threads ( threads)
79+ . build_global ( ) ?;
80+ Ok ( ( ) )
81+ }
0 commit comments