100
100
//!
101
101
//! - rust nightly + `wasm32-unknown-unknown` toolchain
102
102
//!
103
- //! If a specific rust nightly is installed with `rustup`, it is important that the wasm target is
104
- //! installed as well. For example if installing the rust nightly from 20.02.2020 using `rustup
103
+ //! or
104
+ //!
105
+ //! - rust stable and version at least 1.68.0 + `wasm32-unknown-unknown` toolchain
106
+ //!
107
+ //! If a specific rust is installed with `rustup`, it is important that the wasm target is
108
+ //! installed as well. For example if installing the rust from 20.02.2020 using `rustup
105
109
//! install nightly-2020-02-20`, the wasm target needs to be installed as well `rustup target add
106
110
//! wasm32-unknown-unknown --toolchain nightly-2020-02-20`.
107
111
@@ -111,9 +115,11 @@ use std::{
111
115
path:: { Path , PathBuf } ,
112
116
process:: Command ,
113
117
} ;
118
+ use version:: Version ;
114
119
115
120
mod builder;
116
121
mod prerequisites;
122
+ mod version;
117
123
mod wasm_project;
118
124
119
125
pub use builder:: { WasmBuilder , WasmBuilderSelectProject } ;
@@ -172,53 +178,59 @@ fn copy_file_if_changed(src: PathBuf, dst: PathBuf) {
172
178
}
173
179
}
174
180
175
- /// Get a cargo command that compiles with nightly
176
- fn get_nightly_cargo ( ) -> CargoCommand {
181
+ /// Get a cargo command that should be used to invoke the compilation.
182
+ fn get_cargo_command ( ) -> CargoCommand {
177
183
let env_cargo =
178
184
CargoCommand :: new ( & env:: var ( "CARGO" ) . expect ( "`CARGO` env variable is always set by cargo" ) ) ;
179
185
let default_cargo = CargoCommand :: new ( "cargo" ) ;
180
- let rustup_run_nightly = CargoCommand :: new_with_args ( "rustup" , & [ "run" , "nightly" , "cargo" ] ) ;
181
186
let wasm_toolchain = env:: var ( WASM_BUILD_TOOLCHAIN ) . ok ( ) ;
182
187
183
188
// First check if the user requested a specific toolchain
184
- if let Some ( cmd) = wasm_toolchain. and_then ( |t| get_rustup_nightly ( Some ( t) ) ) {
189
+ if let Some ( cmd) =
190
+ wasm_toolchain. map ( |t| CargoCommand :: new_with_args ( "rustup" , & [ "run" , & t, "cargo" ] ) )
191
+ {
185
192
cmd
186
- } else if env_cargo. is_nightly ( ) {
193
+ } else if env_cargo. supports_substrate_wasm_env ( ) {
187
194
env_cargo
188
- } else if default_cargo. is_nightly ( ) {
195
+ } else if default_cargo. supports_substrate_wasm_env ( ) {
189
196
default_cargo
190
- } else if rustup_run_nightly. is_nightly ( ) {
191
- rustup_run_nightly
192
197
} else {
193
- // If no command before provided us with a nightly compiler, we try to search one
194
- // with rustup. If that fails as well, we return the default cargo and let the prequisities
195
- // check fail.
196
- get_rustup_nightly ( None ) . unwrap_or ( default_cargo)
198
+ // If no command before provided us with a cargo that supports our Substrate wasm env, we
199
+ // try to search one with rustup. If that fails as well, we return the default cargo and let
200
+ // the prequisities check fail.
201
+ get_rustup_command ( ) . unwrap_or ( default_cargo)
197
202
}
198
203
}
199
204
200
- /// Get a nightly from rustup. If `selected` is `Some(_)`, a `CargoCommand` using the given
201
- /// nightly is returned.
202
- fn get_rustup_nightly ( selected : Option < String > ) -> Option < CargoCommand > {
205
+ /// Get the newest rustup command that supports our Substrate wasm env.
206
+ ///
207
+ /// Stable versions are always favored over nightly versions even if the nightly versions are
208
+ /// newer.
209
+ fn get_rustup_command ( ) -> Option < CargoCommand > {
203
210
let host = format ! ( "-{}" , env:: var( "HOST" ) . expect( "`HOST` is always set by cargo" ) ) ;
204
211
205
- let version = match selected {
206
- Some ( selected) => selected,
207
- None => {
208
- let output = Command :: new ( "rustup" ) . args ( & [ "toolchain" , "list" ] ) . output ( ) . ok ( ) ?. stdout ;
209
- let lines = output. as_slice ( ) . lines ( ) ;
212
+ let output = Command :: new ( "rustup" ) . args ( & [ "toolchain" , "list" ] ) . output ( ) . ok ( ) ?. stdout ;
213
+ let lines = output. as_slice ( ) . lines ( ) ;
214
+
215
+ let mut versions = Vec :: new ( ) ;
216
+ for line in lines. filter_map ( |l| l. ok ( ) ) {
217
+ let rustup_version = line. trim_end_matches ( & host) ;
218
+
219
+ let cmd = CargoCommand :: new_with_args ( "rustup" , & [ "run" , & rustup_version, "cargo" ] ) ;
210
220
211
- let mut latest_nightly = None ;
212
- for line in lines. filter_map ( |l| l. ok ( ) ) {
213
- if line. starts_with ( "nightly-" ) && line. ends_with ( & host) {
214
- // Rustup prints them sorted
215
- latest_nightly = Some ( line. clone ( ) ) ;
216
- }
217
- }
221
+ if !cmd. supports_substrate_wasm_env ( ) {
222
+ continue
223
+ }
224
+
225
+ let Some ( cargo_version) = cmd. version ( ) else { continue ; } ;
218
226
219
- latest_nightly?. trim_end_matches ( & host) . into ( )
220
- } ,
221
- } ;
227
+ versions. push ( ( cargo_version, rustup_version. to_string ( ) ) ) ;
228
+ }
229
+
230
+ // Sort by the parsed version to get the latest version (greatest version) at the end of the
231
+ // vec.
232
+ versions. sort_by_key ( |v| v. 0 ) ;
233
+ let version = & versions. last ( ) ?. 1 ;
222
234
223
235
Some ( CargoCommand :: new_with_args ( "rustup" , & [ "run" , & version, "cargo" ] ) )
224
236
}
@@ -228,17 +240,23 @@ fn get_rustup_nightly(selected: Option<String>) -> Option<CargoCommand> {
228
240
struct CargoCommand {
229
241
program : String ,
230
242
args : Vec < String > ,
243
+ version : Option < Version > ,
231
244
}
232
245
233
246
impl CargoCommand {
234
247
fn new ( program : & str ) -> Self {
235
- CargoCommand { program : program. into ( ) , args : Vec :: new ( ) }
248
+ let version = Self :: extract_version ( program, & [ ] ) ;
249
+
250
+ CargoCommand { program : program. into ( ) , args : Vec :: new ( ) , version }
236
251
}
237
252
238
253
fn new_with_args ( program : & str , args : & [ & str ] ) -> Self {
254
+ let version = Self :: extract_version ( program, args) ;
255
+
239
256
CargoCommand {
240
257
program : program. into ( ) ,
241
258
args : args. iter ( ) . map ( ToString :: to_string) . collect ( ) ,
259
+ version,
242
260
}
243
261
}
244
262
@@ -248,20 +266,40 @@ impl CargoCommand {
248
266
cmd
249
267
}
250
268
251
- /// Check if the supplied cargo command is a nightly version
252
- fn is_nightly ( & self ) -> bool {
269
+ fn extract_version ( program : & str , args : & [ & str ] ) -> Option < Version > {
270
+ let version = Command :: new ( program)
271
+ . args ( args)
272
+ . arg ( "--version" )
273
+ . output ( )
274
+ . ok ( )
275
+ . and_then ( |o| String :: from_utf8 ( o. stdout ) . ok ( ) ) ?;
276
+
277
+ Version :: extract ( & version)
278
+ }
279
+
280
+ /// Returns the version of this cargo command or `None` if it failed to extract the version.
281
+ fn version ( & self ) -> Option < Version > {
282
+ self . version
283
+ }
284
+
285
+ /// Check if the supplied cargo command supports our Substrate wasm environment.
286
+ ///
287
+ /// This means that either the cargo version is at minimum 1.68.0 or this is a nightly cargo.
288
+ ///
289
+ /// Assumes that cargo version matches the rustc version.
290
+ fn supports_substrate_wasm_env ( & self ) -> bool {
253
291
// `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env
254
292
// variable is set, we can assume that whatever rust compiler we have, it is a nightly
255
293
// compiler. For "more" information, see:
256
294
// https://github.com/rust-lang/rust/blob/fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f/src/libsyntax/feature_gate/check.rs#L891
257
- env:: var ( "RUSTC_BOOTSTRAP" ) . is_ok ( ) ||
258
- self . command ( )
259
- . arg ( "--version" )
260
- . output ( )
261
- . map_err ( |_| ( ) )
262
- . and_then ( |o| String :: from_utf8 ( o . stdout ) . map_err ( |_| ( ) ) )
263
- . unwrap_or_default ( )
264
- . contains ( "-nightly" )
295
+ if env:: var ( "RUSTC_BOOTSTRAP" ) . is_ok ( ) {
296
+ return true
297
+ }
298
+
299
+ let Some ( version ) = self . version ( ) else { return false } ;
300
+
301
+ // Check if major and minor are greater or equal than 1.68 or this is a nightly.
302
+ version . major > 1 || ( version . major == 1 && version . minor >= 68 ) || version . is_nightly
265
303
}
266
304
}
267
305
0 commit comments