@@ -80,7 +80,7 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
80
80
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
81
81
// the tool is actually usable.
82
82
83
- return impl_:: find_msvc_15 ( tool, target)
83
+ return impl_:: find_msvc_15plus ( tool, target)
84
84
. or_else ( || impl_:: find_msvc_14 ( tool, target) )
85
85
. or_else ( || impl_:: find_msvc_12 ( tool, target) )
86
86
. or_else ( || impl_:: find_msvc_11 ( tool, target) ) ;
@@ -173,6 +173,7 @@ mod impl_ {
173
173
use std:: iter;
174
174
use std:: mem;
175
175
use std:: path:: { Path , PathBuf } ;
176
+ use std:: str:: FromStr ;
176
177
177
178
use crate :: Tool ;
178
179
@@ -210,7 +211,7 @@ mod impl_ {
210
211
211
212
#[ allow( bare_trait_objects) ]
212
213
fn vs16_instances ( ) -> Box < Iterator < Item = PathBuf > > {
213
- let instances = if let Some ( instances) = vs15_instances ( ) {
214
+ let instances = if let Some ( instances) = vs15plus_instances ( ) {
214
215
instances
215
216
} else {
216
217
return Box :: new ( iter:: empty ( ) ) ;
@@ -253,24 +254,34 @@ mod impl_ {
253
254
// Note that much of this logic can be found [online] wrt paths, COM, etc.
254
255
//
255
256
// [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/
256
- fn vs15_instances ( ) -> Option < EnumSetupInstances > {
257
+ //
258
+ // Returns MSVC 15+ instances (15, 16 right now), the order should be consider undefined.
259
+ fn vs15plus_instances ( ) -> Option < EnumSetupInstances > {
257
260
com:: initialize ( ) . ok ( ) ?;
258
261
259
262
let config = SetupConfiguration :: new ( ) . ok ( ) ?;
260
263
config. enum_all_instances ( ) . ok ( )
261
264
}
262
265
263
- pub fn find_msvc_15 ( tool : & str , target : & str ) -> Option < Tool > {
264
- let iter = vs15_instances ( ) ?;
265
- for instance in iter {
266
- let instance = instance. ok ( ) ?;
267
- let tool = tool_from_vs15_instance ( tool, target, & instance) ;
268
- if tool. is_some ( ) {
269
- return tool;
270
- }
271
- }
266
+ // Inspired from official microsoft/vswhere ParseVersionString
267
+ // i.e. at most four u16 numbers separated by '.'
268
+ fn parse_version ( version : & str ) -> Option < Vec < u16 > > {
269
+ version
270
+ . split ( '.' )
271
+ . map ( |chunk| u16:: from_str ( chunk) . ok ( ) )
272
+ . collect ( )
273
+ }
272
274
273
- None
275
+ pub fn find_msvc_15plus ( tool : & str , target : & str ) -> Option < Tool > {
276
+ let iter = vs15plus_instances ( ) ?;
277
+ iter. filter_map ( |instance| {
278
+ let instance = instance. ok ( ) ?;
279
+ let version = parse_version ( instance. installation_version ( ) . ok ( ) ?. to_str ( ) ?) ?;
280
+ let tool = tool_from_vs15plus_instance ( tool, target, & instance) ?;
281
+ Some ( ( version, tool) )
282
+ } )
283
+ . max_by ( |( a_version, _) , ( b_version, _) | a_version. cmp ( b_version) )
284
+ . map ( |( _version, tool) | tool)
274
285
}
275
286
276
287
// While the paths to Visual Studio 2017's devenv and MSBuild could
@@ -281,7 +292,7 @@ mod impl_ {
281
292
//
282
293
// [more reliable]: https://github.com/alexcrichton/cc-rs/pull/331
283
294
fn find_tool_in_vs15_path ( tool : & str , target : & str ) -> Option < Tool > {
284
- let mut path = match vs15_instances ( ) {
295
+ let mut path = match vs15plus_instances ( ) {
285
296
Some ( instances) => instances
286
297
. filter_map ( |instance| {
287
298
instance
@@ -312,8 +323,13 @@ mod impl_ {
312
323
} )
313
324
}
314
325
315
- fn tool_from_vs15_instance ( tool : & str , target : & str , instance : & SetupInstance ) -> Option < Tool > {
316
- let ( bin_path, host_dylib_path, lib_path, include_path) = vs15_vc_paths ( target, instance) ?;
326
+ fn tool_from_vs15plus_instance (
327
+ tool : & str ,
328
+ target : & str ,
329
+ instance : & SetupInstance ,
330
+ ) -> Option < Tool > {
331
+ let ( bin_path, host_dylib_path, lib_path, include_path) =
332
+ vs15plus_vc_paths ( target, instance) ?;
317
333
let tool_path = bin_path. join ( tool) ;
318
334
if !tool_path. exists ( ) {
319
335
return None ;
@@ -334,7 +350,7 @@ mod impl_ {
334
350
Some ( tool. into_tool ( ) )
335
351
}
336
352
337
- fn vs15_vc_paths (
353
+ fn vs15plus_vc_paths (
338
354
target : & str ,
339
355
instance : & SetupInstance ,
340
356
) -> Option < ( PathBuf , PathBuf , PathBuf , PathBuf ) > {
0 commit comments