1
+ pub mod run;
2
+
1
3
use std:: env;
2
4
use std:: path:: { Path , PathBuf } ;
3
5
use std:: process:: { Command , Output } ;
4
6
5
7
pub use wasmparser;
6
8
9
+ pub use run:: { run, run_fail} ;
10
+
7
11
pub fn out_dir ( ) -> PathBuf {
8
12
env:: var_os ( "TMPDIR" ) . unwrap ( ) . into ( )
9
13
}
@@ -24,65 +28,148 @@ fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> !
24
28
std:: process:: exit ( 1 )
25
29
}
26
30
27
- pub fn rustc ( ) -> RustcInvocationBuilder {
28
- RustcInvocationBuilder :: new ( )
29
- }
30
-
31
- pub fn aux_build ( ) -> AuxBuildInvocationBuilder {
32
- AuxBuildInvocationBuilder :: new ( )
33
- }
34
-
31
+ /// A `rustc` invocation builder.
35
32
#[ derive( Debug ) ]
36
- pub struct RustcInvocationBuilder {
33
+ pub struct Rustc {
37
34
cmd : Command ,
38
35
}
39
36
40
- impl RustcInvocationBuilder {
41
- fn new ( ) -> Self {
37
+ impl Rustc {
38
+ // `rustc` invocation constructor methods
39
+
40
+ /// Construct a new `rustc` invocation.
41
+ pub fn new ( ) -> Self {
42
42
let cmd = setup_common_build_cmd ( ) ;
43
43
Self { cmd }
44
44
}
45
45
46
- pub fn arg ( & mut self , arg : & str ) -> & mut RustcInvocationBuilder {
47
- self . cmd . arg ( arg) ;
46
+ /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
47
+ pub fn new_aux_build ( ) -> Self {
48
+ let mut cmd = setup_common_build_cmd ( ) ;
49
+ cmd. arg ( "--crate-type=lib" ) ;
50
+ Self { cmd }
51
+ }
52
+
53
+ // Argument provider methods
54
+
55
+ /// Configure the compilation environment.
56
+ pub fn cfg ( & mut self , s : & str ) -> & mut Self {
57
+ self . cmd . arg ( "--cfg" ) ;
58
+ self . cmd . arg ( s) ;
48
59
self
49
60
}
50
61
51
- pub fn args ( & mut self , args : & [ & str ] ) -> & mut RustcInvocationBuilder {
52
- self . cmd . args ( args) ;
62
+ /// Configure codegen options.
63
+ pub fn codegen_opt ( & mut self , c : CodegenOpt ) -> & mut Self {
64
+ self . cmd . arg ( "-C" ) ;
65
+
66
+ match c {
67
+ CodegenOpt :: PreferDynamic => self . cmd . arg ( "prefer-dynamic=true" ) ,
68
+ CodegenOpt :: SymbolManglingVersion ( v) => match v {
69
+ SymbolManglingVersion :: Legacy => self . cmd . arg ( "symbol-mangling-version=legacy" ) ,
70
+ SymbolManglingVersion :: V0 => self . cmd . arg ( "symbol-mangling-version=v0" ) ,
71
+ } ,
72
+ CodegenOpt :: Lto ( kind) => match kind {
73
+ LtoKind :: Fat => self . cmd . arg ( "lto=fat" ) ,
74
+ LtoKind :: Thin => self . cmd . arg ( "lto=thin" ) ,
75
+ LtoKind :: None => self . cmd . arg ( "lto=false" ) ,
76
+ } ,
77
+ CodegenOpt :: OptLevel ( level) => match level {
78
+ OptLevel :: O0 => self . cmd . arg ( "opt-level=0" ) ,
79
+ OptLevel :: O1 => self . cmd . arg ( "opt-level=1" ) ,
80
+ OptLevel :: O2 => self . cmd . arg ( "opt-level=2" ) ,
81
+ OptLevel :: O3 => self . cmd . arg ( "opt-level=3" ) ,
82
+ OptLevel :: Os => self . cmd . arg ( "opt-level=s" ) ,
83
+ OptLevel :: Oz => self . cmd . arg ( "opt-level=z" ) ,
84
+ } ,
85
+ CodegenOpt :: OverflowChecks => self . cmd . arg ( "overflow-checks=true" ) ,
86
+ CodegenOpt :: Panic ( strat) => match strat {
87
+ PanicStrategy :: Abort => self . cmd . arg ( "panic=abort" ) ,
88
+ PanicStrategy :: Unwind => self . cmd . arg ( "panic=unwind" ) ,
89
+ } ,
90
+ } ;
91
+
53
92
self
54
93
}
55
94
56
- #[ track_caller]
57
- pub fn run ( & mut self ) -> Output {
58
- let caller_location = std:: panic:: Location :: caller ( ) ;
59
- let caller_line_number = caller_location. line ( ) ;
95
+ /// Specify default optimization level `-O` (alias for `-C opt-level=2`).
96
+ pub fn default_opt ( & mut self ) -> & mut Self {
97
+ self . cmd . arg ( "-O" ) ;
98
+ self
99
+ }
60
100
61
- let output = self . cmd . output ( ) . unwrap ( ) ;
62
- if !output. status . success ( ) {
63
- handle_failed_output ( & format ! ( "{:#?}" , self . cmd) , output, caller_line_number) ;
64
- }
65
- output
101
+ /// Specify types of output files to generate. See [`EmitKind`] for kinds.
102
+ pub fn emit ( & mut self , kinds : & [ EmitKind ] ) -> & mut Self {
103
+ let kinds = kinds
104
+ . iter ( )
105
+ . map ( |kind| match kind {
106
+ EmitKind :: Metadata => "metadata" ,
107
+ } )
108
+ . collect :: < Vec < _ > > ( ) ;
109
+ let kinds_str: String = kinds. join ( "," ) ;
110
+ self . cmd . arg ( format ! ( "--emit={kinds_str}" ) ) ;
111
+ self
66
112
}
67
- }
68
113
69
- #[ derive( Debug ) ]
70
- pub struct AuxBuildInvocationBuilder {
71
- cmd : Command ,
72
- }
114
+ /// Set `-Z unstable-options`
115
+ pub fn enable_unstable_options ( & mut self ) -> & mut Self {
116
+ self . cmd . arg ( "-Z" ) ;
117
+ self . cmd . arg ( "unstable-options" ) ;
118
+ self
119
+ }
73
120
74
- impl AuxBuildInvocationBuilder {
75
- fn new ( ) -> Self {
76
- let mut cmd = setup_common_build_cmd ( ) ;
77
- cmd. arg ( "--crate-type=lib" ) ;
78
- Self { cmd }
121
+ /// Specify where an external library is located.
122
+ pub fn extern_ < P : AsRef < Path > > ( & mut self , crate_name : & str , path : P ) -> & mut Self {
123
+ assert ! (
124
+ !crate_name. contains( |c: char | c. is_whitespace( ) || c == '\\' || c == '/' ) ,
125
+ "crate name cannot contain whitespace or path separators"
126
+ ) ;
127
+
128
+ let path = path. as_ref ( ) . to_string_lossy ( ) ;
129
+
130
+ self . cmd . arg ( "--extern" ) ;
131
+ self . cmd . arg ( format ! ( "{crate_name}={path}" ) ) ;
132
+
133
+ self
79
134
}
80
135
81
- pub fn arg ( & mut self , arg : & str ) -> & mut AuxBuildInvocationBuilder {
136
+ /// Specify path to the input file.
137
+ pub fn input_file < P : AsRef < Path > > ( & mut self , path : P ) -> & mut Self {
138
+ self . cmd . arg ( path. as_ref ( ) ) ;
139
+ self
140
+ }
141
+
142
+ /// Specify target triple.
143
+ pub fn target ( & mut self , target : & str ) -> & mut Self {
144
+ assert ! ( !target. contains( char :: is_whitespace) , "target triple cannot contain spaces" ) ;
145
+ self . cmd . arg ( format ! ( "--target={target}" ) ) ;
146
+ self
147
+ }
148
+
149
+ // Last-resort builder methods
150
+
151
+ /// Fallback command argument provider. Prefer using semantically meaningful builder methods
152
+ /// (add them if they don't exist) whenever possible.
153
+ pub fn arg ( & mut self , arg : & str ) -> & mut Self {
82
154
self . cmd . arg ( arg) ;
83
155
self
84
156
}
85
157
158
+ /// Fallback command arguments provider. Prefer using semantically meaningful builder methods
159
+ /// (add them if they don't exist) whenever possible.
160
+ pub fn args ( & mut self , args : & [ & str ] ) -> & mut Self {
161
+ self . cmd . args ( args) ;
162
+ self
163
+ }
164
+
165
+ // Command inspection, output and running helper methods
166
+
167
+ /// Get the [`Output`][std::process::Output] of the finished `rustc` process.
168
+ pub fn output ( & mut self ) -> Output {
169
+ self . cmd . output ( ) . unwrap ( )
170
+ }
171
+
172
+ /// Run the constructed `rustc` command and assert that it is successfully run.
86
173
#[ track_caller]
87
174
pub fn run ( & mut self ) -> Output {
88
175
let caller_location = std:: panic:: Location :: caller ( ) ;
@@ -94,66 +181,81 @@ impl AuxBuildInvocationBuilder {
94
181
}
95
182
output
96
183
}
97
- }
98
184
99
- fn run_common ( bin_name : & str ) -> ( Command , Output ) {
100
- let target = env:: var ( "TARGET" ) . unwrap ( ) ;
101
-
102
- let bin_name =
103
- if target. contains ( "windows" ) { format ! ( "{}.exe" , bin_name) } else { bin_name. to_owned ( ) } ;
104
-
105
- let mut bin_path = PathBuf :: new ( ) ;
106
- bin_path. push ( env:: var ( "TMPDIR" ) . unwrap ( ) ) ;
107
- bin_path. push ( & bin_name) ;
108
- let ld_lib_path_envvar = env:: var ( "LD_LIB_PATH_ENVVAR" ) . unwrap ( ) ;
109
- let mut cmd = Command :: new ( bin_path) ;
110
- cmd. env ( & ld_lib_path_envvar, {
111
- let mut paths = vec ! [ ] ;
112
- paths. push ( PathBuf :: from ( env:: var ( "TMPDIR" ) . unwrap ( ) ) ) ;
113
- for p in env:: split_paths ( & env:: var ( "TARGET_RPATH_ENV" ) . unwrap ( ) ) {
114
- paths. push ( p. to_path_buf ( ) ) ;
115
- }
116
- for p in env:: split_paths ( & env:: var ( & ld_lib_path_envvar) . unwrap ( ) ) {
117
- paths. push ( p. to_path_buf ( ) ) ;
118
- }
119
- env:: join_paths ( paths. iter ( ) ) . unwrap ( )
120
- } ) ;
121
-
122
- if target. contains ( "windows" ) {
123
- let mut paths = vec ! [ ] ;
124
- for p in env:: split_paths ( & std:: env:: var ( "PATH" ) . unwrap_or ( String :: new ( ) ) ) {
125
- paths. push ( p. to_path_buf ( ) ) ;
126
- }
127
- paths. push ( Path :: new ( & std:: env:: var ( "TARGET_RPATH_DIR" ) . unwrap ( ) ) . to_path_buf ( ) ) ;
128
- cmd. env ( "PATH" , env:: join_paths ( paths. iter ( ) ) . unwrap ( ) ) ;
185
+ /// Inspect what the underlying [`Command`] is up to the current construction.
186
+ pub fn inspect ( & mut self , f : impl FnOnce ( & Command ) ) -> & mut Self {
187
+ f ( & self . cmd ) ;
188
+ self
129
189
}
190
+ }
130
191
131
- let output = cmd. output ( ) . unwrap ( ) ;
132
- ( cmd, output)
192
+ /// Specifies the types of output files to generate.
193
+ pub enum EmitKind {
194
+ /// Generates a file containing metadata about the crate. The default output filename is
195
+ /// `libCRATE_NAME.rmeta`.
196
+ Metadata ,
133
197
}
134
198
135
- /// Run a built binary and make sure it succeeds.
136
- #[ track_caller]
137
- pub fn run ( bin_name : & str ) -> Output {
138
- let caller_location = std:: panic:: Location :: caller ( ) ;
139
- let caller_line_number = caller_location. line ( ) ;
199
+ /// Specifies codegen options.
200
+ pub enum CodegenOpt {
201
+ /// By default, rustc prefers to statically link dependencies. This option will indicate that
202
+ /// dynamic linking should be used if possible if both a static and dynamic versions of a
203
+ /// library are available.
204
+ PreferDynamic ,
205
+ /// Controls the name mangling format for encoding Rust item names for the purpose of generating
206
+ /// object code and linking.
207
+ SymbolManglingVersion ( SymbolManglingVersion ) ,
208
+ /// Controls whether LLVM uses link time optimizations to produce better optimized code, using
209
+ /// whole-program analysis, at the cost of longer linking time.
210
+ Lto ( LtoKind ) ,
211
+ ///
212
+ OptLevel ( OptLevel ) ,
213
+ /// Control the behavior of runtime integer overflow. When `overflow-checks` are enabled, a
214
+ /// panic will occur on overflow.
215
+ OverflowChecks ,
216
+ /// Control what happens when the code panics.
217
+ Panic ( PanicStrategy ) ,
218
+ }
140
219
141
- let ( cmd , output ) = run_common ( bin_name ) ;
142
- if !output . status . success ( ) {
143
- handle_failed_output ( & format ! ( "{:#?}" , cmd ) , output , caller_line_number ) ;
144
- }
145
- output
220
+ /// The name mangling format for encoding Rust item names for the purpose of generating object code
221
+ /// and linking.
222
+ pub enum SymbolManglingVersion {
223
+ Legacy ,
224
+ V0 ,
146
225
}
147
226
148
- /// Run a built binary and make sure it fails.
149
- #[ track_caller]
150
- pub fn run_fail ( bin_name : & str ) -> Output {
151
- let caller_location = std:: panic:: Location :: caller ( ) ;
152
- let caller_line_number = caller_location. line ( ) ;
227
+ /// Kind of LTO to perform.
228
+ pub enum LtoKind {
229
+ /// Perform "fat" LTO which attempts to perform optimizations across all crates within the
230
+ /// dependency graph.
231
+ Fat ,
232
+ /// Similar to "fat", but takes substantially less time to run while still achieving performance
233
+ /// gains similar to "fat".
234
+ Thin ,
235
+ /// Disable LTO.
236
+ None ,
237
+ }
153
238
154
- let ( cmd, output) = run_common ( bin_name) ;
155
- if output. status . success ( ) {
156
- handle_failed_output ( & format ! ( "{:#?}" , cmd) , output, caller_line_number) ;
157
- }
158
- output
239
+ /// Optimization level.
240
+ pub enum OptLevel {
241
+ /// No optimizations, also turns on `cfg(debug_assertions)` (the default).
242
+ O0 ,
243
+ /// Basic optimizations.
244
+ O1 ,
245
+ /// Some optimizations.
246
+ O2 ,
247
+ /// All optimizations.
248
+ O3 ,
249
+ /// Optimize for binary size.
250
+ Os ,
251
+ /// Optimize for binary size, but also turn off loop vectorization.
252
+ Oz ,
253
+ }
254
+
255
+ /// What happens when the code panics.
256
+ pub enum PanicStrategy {
257
+ /// Terminate the process upon panic.
258
+ Abort ,
259
+ /// Unwind the stack upon panic.
260
+ Unwind ,
159
261
}
0 commit comments