diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 976699702b..cf903c129c 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -37,8 +37,12 @@ def _get_compiler_version_output(compiler_path, version_arg, ignore_errors=()): version_arg (str): the argument used to extract version information """ compiler = spack.util.executable.Executable(compiler_path) - output = compiler( - version_arg, output=str, error=str, ignore_errors=ignore_errors) + if version_arg: + output = compiler( + version_arg, output=str, error=str, ignore_errors=ignore_errors) + else: + output = compiler( + output=str, error=str, ignore_errors=ignore_errors) return output diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py index ac5da84705..a613d02d36 100644 --- a/lib/spack/spack/compilers/msvc.py +++ b/lib/spack/spack/compilers/msvc.py @@ -3,7 +3,11 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import os +import subprocess +import sys from typing import List # novm + from spack.compiler import Compiler @@ -26,6 +30,22 @@ class Msvc(Compiler): 'f77': '', 'fc': ''} + #: Compiler argument that produces version information + version_argument = '' + + #: Regex used to extract version from compiler's output + version_regex = r'([1-9][0-9]*\.[0-9]*\.[0-9]*)' + + # Initialize, deferring to base class but then adding the vcvarsallfile + # file based on compiler executable path. + + def __init__(self, *args, **kwargs): + super(Msvc, self).__init__(*args, **kwargs) + self.vcvarsallfile = os.path.abspath( + os.path.join(self.cc, '../../../../../../..')) + self.vcvarsallfile = os.path.join( + self.vcvarsallfile, 'Auxiliary', 'Build', 'vcvarsall.bat') + @property def verbose_flag(self): return "" @@ -33,3 +53,30 @@ def verbose_flag(self): @property def pic_flag(self): return "" + + def setup_custom_environment(self, pkg, env): + """Set environment variables for MSVC using the Microsoft-provided + script.""" + if sys.version_info[:2] > (2, 6): + # Capture output from batch script and DOS environment dump + out = subprocess.check_output( # novermin + 'cmd /u /c "{0}" {1} && set'.format(self.vcvarsallfile, 'amd64'), + stderr=subprocess.STDOUT) + if sys.version_info[0] >= 3: + out = out.decode('utf-16le', errors='replace') + else: + print("Cannot pull msvc compiler information in Python 2.6 or below") + + # Process in to nice Python dictionary + vc_env = { # novermin + key.lower(): value + for key, _, value in + (line.partition('=') for line in out.splitlines()) + if key and value + } + + # Request setting environment variables + if 'path' in vc_env: + env.set_path('PATH', vc_env['path'].split(';')) + env.set_path('INCLUDE', vc_env.get('include', '').split(';')) + env.set_path('LIB', vc_env.get('lib', '').split(';')) diff --git a/lib/spack/spack/operating_systems/windows_os.py b/lib/spack/spack/operating_systems/windows_os.py index c4f8fa7f84..a9132c7bce 100755 --- a/lib/spack/spack/operating_systems/windows_os.py +++ b/lib/spack/spack/operating_systems/windows_os.py @@ -3,6 +3,10 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import sys +import os +import subprocess +import glob from spack.architecture import OperatingSystem from spack.version import Version @@ -22,6 +26,35 @@ class WindowsOs(OperatingSystem): using the major version operating system number, e.g. 10. """ + # Find MSVC directories using vswhere + compSearchPaths = [] + root = os.environ.get('ProgramFiles(x86)') or os.environ.get('ProgramFiles') + if root: + try: + extra_args = {} + if sys.version_info[:3] >= (3, 6, 0): + extra_args = {'encoding': 'mbcs', 'errors': 'strict'} + paths = subprocess.check_output([ + os.path.join(root, "Microsoft Visual Studio", "Installer", + "vswhere.exe"), + "-prerelease", + "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-property", "installationPath", + "-products", "*", + ], **extra_args).strip() + if (3, 0) <= sys.version_info[:2] <= (3, 5): + paths = paths.decode() + msvcPaths = paths.split('\n') + msvcPaths = [os.path.join(path, "VC", "Tools", "MSVC") + for path in msvcPaths] + for p in msvcPaths: + compSearchPaths.extend( + glob.glob(os.path.join(p, '*', 'bin', 'Hostx64', 'x64'))) + except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): + pass + if compSearchPaths: + compiler_search_paths = compSearchPaths + def __init__(self): super(WindowsOs, self).__init__('Windows10', '10')