88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- //! A helper module to probe the Windows Registry when looking for
12- //! windows-specific tools.
11+ //! A helper module to looking for windows-specific tools:
12+ //! 1. On Windows host, probe the Windows Registry if needed;
13+ //! 2. On non-Windows host, check specified environment variables.
14+
15+ #![ allow( clippy:: upper_case_acronyms) ]
1316
1417#![ allow( clippy:: upper_case_acronyms) ]
1518
1619use std:: process:: Command ;
1720
1821use crate :: Tool ;
19- #[ cfg( windows) ]
2022use crate :: ToolFamily ;
2123
22- #[ cfg( windows) ]
2324const MSVC_FAMILY : ToolFamily = ToolFamily :: Msvc { clang_cl : false } ;
2425
25- /// Attempts to find a tool within an MSVC installation using the Windows
26- /// registry as a point to search from.
26+ #[ derive( Copy , Clone ) ]
27+ struct TargetArch < ' a > ( pub & ' a str ) ;
28+
29+ impl PartialEq < & str > for TargetArch < ' _ > {
30+ fn eq ( & self , other : & & str ) -> bool {
31+ self . 0 == * other
32+ }
33+ }
34+
35+ impl < ' a > From < TargetArch < ' a > > for & ' a str {
36+ fn from ( target : TargetArch < ' a > ) -> Self {
37+ target. 0
38+ }
39+ }
40+
41+ /// Attempts to find a tool within an MSVC installation:
42+ /// 1. On Windows host, using the Windows registry as a point to search from;
43+ /// 2. On non-Windows host, using related environment variables to search from.
44+ ///
2745///
2846/// The `target` argument is the target that the tool should work for (e.g.
2947/// compile or link for) and the `tool` argument is the tool to find (e.g.
@@ -41,13 +59,6 @@ pub fn find(target: &str, tool: &str) -> Option<Command> {
4159/// Similar to the `find` function above, this function will attempt the same
4260/// operation (finding a MSVC tool in a local install) but instead returns a
4361/// `Tool` which may be introspected.
44- #[ cfg( not( windows) ) ]
45- pub fn find_tool ( _target : & str , _tool : & str ) -> Option < Tool > {
46- None
47- }
48-
49- /// Documented above.
50- #[ cfg( windows) ]
5162pub fn find_tool ( target : & str , tool : & str ) -> Option < Tool > {
5263 // This logic is all tailored for MSVC, if we're not that then bail out
5364 // early.
@@ -56,15 +67,16 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
5667 }
5768
5869 // Split the target to get the arch.
59- let target = impl_ :: TargetArch ( target. split_once ( '-' ) ?. 0 ) ;
70+ let target = TargetArch ( target. split_once ( '-' ) ?. 0 ) ;
6071
6172 // Looks like msbuild isn't located in the same location as other tools like
62- // cl.exe and lib.exe. To handle this we probe for it manually with
63- // dedicated registry keys.
73+ // cl.exe and lib.exe.
6474 if tool. contains ( "msbuild" ) {
6575 return impl_:: find_msbuild ( target) ;
6676 }
6777
78+ // Looks like devenv isn't located in the same location as other tools like
79+ // cl.exe and lib.exe.
6880 if tool. contains ( "devenv" ) {
6981 return impl_:: find_devenv ( target) ;
7082 }
@@ -103,17 +115,8 @@ pub enum VsVers {
103115///
104116/// This is used by the cmake crate to figure out the correct
105117/// generator.
106- #[ cfg( not( windows) ) ]
107- pub fn find_vs_version ( ) -> Result < VsVers , String > {
108- Err ( "not windows" . to_string ( ) )
109- }
110-
111- /// Documented above
112- #[ cfg( windows) ]
113118pub fn find_vs_version ( ) -> Result < VsVers , String > {
114- use std:: env;
115-
116- match env:: var ( "VisualStudioVersion" ) {
119+ match std:: env:: var ( "VisualStudioVersion" ) {
117120 Ok ( version) => match & version[ ..] {
118121 "17.0" => Ok ( VsVers :: Vs17 ) ,
119122 "16.0" => Ok ( VsVers :: Vs16 ) ,
@@ -157,6 +160,7 @@ pub fn find_vs_version() -> Result<VsVers, String> {
157160 }
158161}
159162
163+ /// Windows Implementation.
160164#[ cfg( windows) ]
161165mod impl_ {
162166 use crate :: com;
@@ -174,24 +178,9 @@ mod impl_ {
174178 use std:: process:: Command ;
175179 use std:: str:: FromStr ;
176180
177- use super :: MSVC_FAMILY ;
181+ use super :: { TargetArch , MSVC_FAMILY } ;
178182 use crate :: Tool ;
179183
180- #[ derive( Copy , Clone ) ]
181- pub struct TargetArch < ' a > ( pub & ' a str ) ;
182-
183- impl PartialEq < & str > for TargetArch < ' _ > {
184- fn eq ( & self , other : & & str ) -> bool {
185- self . 0 == * other
186- }
187- }
188-
189- impl < ' a > From < TargetArch < ' a > > for & ' a str {
190- fn from ( target : TargetArch < ' a > ) -> Self {
191- target. 0
192- }
193- }
194-
195184 struct MsvcTool {
196185 tool : PathBuf ,
197186 libs : Vec < PathBuf > ,
@@ -242,7 +231,7 @@ mod impl_ {
242231 }
243232
244233 /// Attempt to find the tool using environment variables set by vcvars.
245- pub fn find_msvc_environment ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
234+ pub ( super ) fn find_msvc_environment ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
246235 // Early return if the environment doesn't contain a VC install.
247236 if env:: var_os ( "VCINSTALLDIR" ) . is_none ( ) {
248237 return None ;
@@ -394,7 +383,7 @@ mod impl_ {
394383 . collect ( )
395384 }
396385
397- pub fn find_msvc_15plus ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
386+ pub ( super ) fn find_msvc_15plus ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
398387 let iter = vs15plus_instances ( target) ?;
399388 iter. into_iter ( )
400389 . filter_map ( |instance| {
@@ -565,7 +554,7 @@ mod impl_ {
565554
566555 // For MSVC 14 we need to find the Universal CRT as well as either
567556 // the Windows 10 SDK or Windows 8.1 SDK.
568- pub fn find_msvc_14 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
557+ pub ( super ) fn find_msvc_14 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
569558 let vcdir = get_vc_dir ( "14.0" ) ?;
570559 let mut tool = get_tool ( tool, & vcdir, target) ?;
571560 add_sdks ( & mut tool, target) ?;
@@ -615,7 +604,7 @@ mod impl_ {
615604 }
616605
617606 // For MSVC 12 we need to find the Windows 8.1 SDK.
618- pub fn find_msvc_12 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
607+ pub ( super ) fn find_msvc_12 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
619608 let vcdir = get_vc_dir ( "12.0" ) ?;
620609 let mut tool = get_tool ( tool, & vcdir, target) ?;
621610 let sub = lib_subdir ( target) ?;
@@ -631,7 +620,7 @@ mod impl_ {
631620 }
632621
633622 // For MSVC 11 we need to find the Windows 8 SDK.
634- pub fn find_msvc_11 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
623+ pub ( super ) fn find_msvc_11 ( tool : & str , target : TargetArch < ' _ > ) -> Option < Tool > {
635624 let vcdir = get_vc_dir ( "11.0" ) ?;
636625 let mut tool = get_tool ( tool, & vcdir, target) ?;
637626 let sub = lib_subdir ( target) ?;
@@ -885,7 +874,7 @@ mod impl_ {
885874 max_key
886875 }
887876
888- pub fn has_msbuild_version ( version : & str ) -> bool {
877+ pub ( super ) fn has_msbuild_version ( version : & str ) -> bool {
889878 match version {
890879 "17.0" => {
891880 find_msbuild_vs17 ( TargetArch ( "x86_64" ) ) . is_some ( )
@@ -912,16 +901,18 @@ mod impl_ {
912901 }
913902 }
914903
915- pub fn find_devenv ( target : TargetArch < ' _ > ) -> Option < Tool > {
904+ // To find devenv we probe for it manually with dedicated registry keys.
905+ pub ( super ) fn find_devenv ( target : TargetArch < ' _ > ) -> Option < Tool > {
916906 find_devenv_vs15 ( target)
917907 }
918908
919909 fn find_devenv_vs15 ( target : TargetArch < ' _ > ) -> Option < Tool > {
920910 find_tool_in_vs15_path ( r"Common7\IDE\devenv.exe" , target)
921911 }
922912
913+ // To find msbuild we probe for it manually with dedicated registry keys.
923914 // see http://stackoverflow.com/questions/328017/path-to-msbuild
924- pub fn find_msbuild ( target : TargetArch < ' _ > ) -> Option < Tool > {
915+ pub ( super ) fn find_msbuild ( target : TargetArch < ' _ > ) -> Option < Tool > {
925916 // VS 15 (2017) changed how to locate msbuild
926917 if let Some ( r) = find_msbuild_vs17 ( target) {
927918 Some ( r)
@@ -957,3 +948,73 @@ mod impl_ {
957948 } )
958949 }
959950}
951+
952+ /// Non-Windows Implementation.
953+ #[ cfg( not( windows) ) ]
954+ mod impl_ {
955+ use std:: { env, ffi:: OsString } ;
956+
957+ use super :: { TargetArch , MSVC_FAMILY } ;
958+ use crate :: Tool ;
959+
960+ /// Finding msbuild.exe tool under unix system is not currently supported.
961+ /// Maybe can check it using an environment variable looks like `MSBUILD_BIN`.
962+ pub ( super ) fn find_msbuild ( _target : TargetArch < ' _ > ) -> Option < Tool > {
963+ None
964+ }
965+
966+ // Finding devenv.exe tool under unix system is not currently supported.
967+ // Maybe can check it using an environment variable looks like `DEVENV_BIN`.
968+ pub ( super ) fn find_devenv ( _target : TargetArch < ' _ > ) -> Option < Tool > {
969+ None
970+ }
971+
972+ /// Attempt to find the tool using environment variables set by vcvars.
973+ pub ( super ) fn find_msvc_environment ( tool : & str , _target : TargetArch < ' _ > ) -> Option < Tool > {
974+ // Early return if the environment doesn't contain a VC install.
975+ let _vc_install_dir = env:: var_os ( "VCINSTALLDIR" ) ?;
976+ let _vs_install_dir = env:: var_os ( "VSINSTALLDIR" ) ?;
977+
978+ // Should we take the path of tool for the v[c|s] install dir?
979+ // Both `VCINSTALLDIR` / `VSINSTALLDIR` are unused currently.
980+
981+ // Fallback to simply using the current environment.
982+ env:: var_os ( "PATH" )
983+ . and_then ( |path : OsString | {
984+ env:: split_paths ( & path)
985+ . map ( |p| p. join ( tool) )
986+ . find ( |p| p. exists ( ) )
987+ } )
988+ . map ( |path| Tool :: with_family ( path. into ( ) , MSVC_FAMILY ) )
989+ }
990+
991+ pub ( super ) fn find_msvc_15plus ( _tool : & str , _target : TargetArch < ' _ > ) -> Option < Tool > {
992+ None
993+ }
994+
995+ // For MSVC 14 we need to find the Universal CRT as well as either
996+ // the Windows 10 SDK or Windows 8.1 SDK.
997+ pub ( super ) fn find_msvc_14 ( _tool : & str , _target : TargetArch < ' _ > ) -> Option < Tool > {
998+ None
999+ }
1000+
1001+ // For MSVC 12 we need to find the Windows 8.1 SDK.
1002+ pub ( super ) fn find_msvc_12 ( _tool : & str , _target : TargetArch < ' _ > ) -> Option < Tool > {
1003+ None
1004+ }
1005+
1006+ // For MSVC 11 we need to find the Windows 8 SDK.
1007+ pub ( super ) fn find_msvc_11 ( _tool : & str , _target : TargetArch < ' _ > ) -> Option < Tool > {
1008+ None
1009+ }
1010+
1011+ pub ( super ) fn has_msbuild_version ( version : & str ) -> bool {
1012+ match version {
1013+ "17.0" => false ,
1014+ "16.0" => false ,
1015+ "15.0" => false ,
1016+ "12.0" | "14.0" => false ,
1017+ _ => false ,
1018+ }
1019+ }
1020+ }
0 commit comments