From 1926ebf1e787a09ef932034c1628f99e23105f0a Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Thu, 30 Mar 2017 13:35:16 +0200
Subject: [PATCH] Enhanced Visual Studio detection

- VC 15 (2017) does not set an environment variable any more
- fallback to filesystem search
---
 cpu/cpujit.py         |  3 ++-
 cpu/msvc_detection.py | 33 +++++++++++++++++++++++++++------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/cpu/cpujit.py b/cpu/cpujit.py
index 7e1891e48..cdb73b82c 100644
--- a/cpu/cpujit.py
+++ b/cpu/cpujit.py
@@ -29,7 +29,8 @@ Then 'cl.exe' is used to compile.
 
 - **'os'**: should be detected automatically as 'windows'
 - **'msvcVersion'**:  either a version number, year number, 'auto' or 'latest' for automatic detection of latest
-                      installed version or 'setuptools' for setuptools-based detection
+                      installed version or 'setuptools' for setuptools-based detection. Alternatively path to folder
+                      where Visual Studio is installed. This path has to contain a file called 'vcvarsall.bat'
 - **'arch'**: 'x86' or 'x64'
 - **'flags'**: flags passed to 'cl.exe', make sure OpenMP is activated
 - **'restrictQualifier'**: the restrict qualifier is not standardized accross compilers.
diff --git a/cpu/msvc_detection.py b/cpu/msvc_detection.py
index 61cfe4aed..b14541096 100644
--- a/cpu/msvc_detection.py
+++ b/cpu/msvc_detection.py
@@ -11,12 +11,23 @@ def getEnvironment(versionSpecifier, arch='x64'):
     """
     if versionSpecifier == 'setuptools':
         return getEnvironmentFromSetupTools(arch)
+    elif '\\' in versionSpecifier:
+        vcVarsPath = findVcVarsAllViaFilesystemSearch(versionSpecifier)
+        return getEnvironmentFromVcVarsFile(vcVarsPath, arch)
     else:
-        if versionSpecifier in ('auto', 'latest'):
-            versionNr = findLatestMsvcVersionUsingEnvironmentVariables()
-        else:
-            versionNr = normalizeMsvcVersion(versionSpecifier)
-        vcVarsPath = getVcVarsPath(versionNr)
+        try:
+            if versionSpecifier in ('auto', 'latest'):
+                versionNr = findLatestMsvcVersionUsingEnvironmentVariables()
+            else:
+                versionNr = normalizeMsvcVersion(versionSpecifier)
+            vcVarsPath = getVcVarsPathViaEnvironmentVariable(versionNr)
+        except ValueError:
+            vcVarsPath = findVcVarsAllViaFilesystemSearch("C:\\Program Files (x86)\\Microsoft Visual Studio")
+            if vcVarsPath is None:
+                vcVarsPath = findVcVarsAllViaFilesystemSearch("C:\\Program Files\\Microsoft Visual Studio")
+            if vcVarsPath is None:
+                raise ValueError("Visual Studio not found. Write path to VS folder in pystencils config")
+
         return getEnvironmentFromVcVarsFile(vcVarsPath, arch)
 
 
@@ -66,7 +77,7 @@ def getEnvironmentFromVcVarsFile(vcVarsFile, arch):
     return env
 
 
-def getVcVarsPath(versionNr):
+def getVcVarsPathViaEnvironmentVariable(versionNr):
     environmentVarName = 'VS%d0COMNTOOLS' % (versionNr,)
     vcPath = os.environ[environmentVarName]
     path = os.path.join(vcPath, '..', '..', 'VC', 'vcvarsall.bat')
@@ -79,3 +90,13 @@ def getEnvironmentFromSetupTools(arch):
     return {k.upper(): v for k, v in msvcEnv.items()}
 
 
+def findVcVarsAllViaFilesystemSearch(basePath):
+    matches = []
+    for root, dirnames, filenames in os.walk(basePath):
+        for filename in filenames:
+            if filename == 'vcvarsall.bat':
+                matches.append(os.path.join(root, filename))
+
+    matches.sort(reverse=True)
+    if matches:
+        return matches[0]
-- 
GitLab