MSVC Compiler Find and vcvars env integration (#22856)
Made the vcvars batch script location a member variable of the msvc compiler subclass, initialized from the compiler executable path. Added a setup_custom_environment() method to the msvc subclass that sources the vcvars script, dumps the environment, and copies the relevant environment variables to the Spack environment. Added class variables to the Windows OS and MSVC compiler subclasses to enable finding the compiler executables and determining their versions.
This commit is contained in:
parent
f587a9ce68
commit
a7101db39d
3 changed files with 86 additions and 2 deletions
|
@ -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
|
version_arg (str): the argument used to extract version information
|
||||||
"""
|
"""
|
||||||
compiler = spack.util.executable.Executable(compiler_path)
|
compiler = spack.util.executable.Executable(compiler_path)
|
||||||
|
if version_arg:
|
||||||
output = compiler(
|
output = compiler(
|
||||||
version_arg, output=str, error=str, ignore_errors=ignore_errors)
|
version_arg, output=str, error=str, ignore_errors=ignore_errors)
|
||||||
|
else:
|
||||||
|
output = compiler(
|
||||||
|
output=str, error=str, ignore_errors=ignore_errors)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
from typing import List # novm
|
from typing import List # novm
|
||||||
|
|
||||||
from spack.compiler import Compiler
|
from spack.compiler import Compiler
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +30,22 @@ class Msvc(Compiler):
|
||||||
'f77': '',
|
'f77': '',
|
||||||
'fc': ''}
|
'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
|
@property
|
||||||
def verbose_flag(self):
|
def verbose_flag(self):
|
||||||
return ""
|
return ""
|
||||||
|
@ -33,3 +53,30 @@ def verbose_flag(self):
|
||||||
@property
|
@property
|
||||||
def pic_flag(self):
|
def pic_flag(self):
|
||||||
return ""
|
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(';'))
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import glob
|
||||||
from spack.architecture import OperatingSystem
|
from spack.architecture import OperatingSystem
|
||||||
from spack.version import Version
|
from spack.version import Version
|
||||||
|
|
||||||
|
@ -22,6 +26,35 @@ class WindowsOs(OperatingSystem):
|
||||||
using the major version operating system number, e.g. 10.
|
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):
|
def __init__(self):
|
||||||
super(WindowsOs, self).__init__('Windows10', '10')
|
super(WindowsOs, self).__init__('Windows10', '10')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue