diff options
Diffstat (limited to 'src/engine/SCons/Tool/MSCommon')
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/__init__.py | 7 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/arch.py | 4 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/common.py | 100 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/netframework.py | 14 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/sdk.py | 51 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py | 162 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/MSCommon/vs.py | 31 | 
7 files changed, 228 insertions, 141 deletions
diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index 6b637fe..989ab08 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  # -__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """  Common functions for Microsoft Visual Studio and Visual C/C++. @@ -41,7 +41,8 @@ from SCons.Tool.MSCommon.sdk import mssdk_exists, \  from SCons.Tool.MSCommon.vc import msvc_exists, \                                     msvc_setup_env, \ -                                   msvc_setup_env_once +                                   msvc_setup_env_once, \ +                                   msvc_version_to_maj_min  from SCons.Tool.MSCommon.vs import get_default_version, \                                     get_vs_by_version, \ diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py index 46fb601..96f05a8 100644 --- a/src/engine/SCons/Tool/MSCommon/arch.py +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  # -__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """Module to define supported Windows chip architectures.  """ diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 1467543..fcf623f 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -1,5 +1,8 @@ +""" +Common helper functions for working with the Microsoft tool chain. +"""  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -20,12 +23,9 @@  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  # +from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -__doc__ = """ -Common helper functions for working with the Microsoft tool chain. -""" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  import copy  import os @@ -35,17 +35,17 @@ import re  import SCons.Util -logfile = os.environ.get('SCONS_MSCOMMON_DEBUG') -if logfile == '-': -    def debug(x): -        print x -elif logfile: +LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') +if LOGFILE == '-': +    def debug(message): +        print(message) +elif LOGFILE:      try:          import logging      except ImportError: -        debug = lambda x: open(logfile, 'a').write(x + '\n') +        debug = lambda message: open(LOGFILE, 'a').write(message + '\n')      else: -        logging.basicConfig(filename=logfile, level=logging.DEBUG) +        logging.basicConfig(filename=LOGFILE, level=logging.DEBUG)          debug = logging.debug  else:      debug = lambda x: None @@ -75,7 +75,7 @@ def is_win64():          # I structured these tests to make it easy to add new ones or          # add exceptions in the future, because this is a bit fragile.          _is_win64 = False -        if os.environ.get('PROCESSOR_ARCHITECTURE','x86') != 'x86': +        if os.environ.get('PROCESSOR_ARCHITECTURE', 'x86') != 'x86':              _is_win64 = True          if os.environ.get('PROCESSOR_ARCHITEW6432'):              _is_win64 = True @@ -113,21 +113,30 @@ def normalize_env(env, keys, force=False):      Note: the environment is copied."""      normenv = {}      if env: -        for k in env.keys(): -            normenv[k] = copy.deepcopy(env[k]).encode('mbcs') +        for k in list(env.keys()): +            normenv[k] = copy.deepcopy(env[k])          for k in keys:              if k in os.environ and (force or not k in normenv): -                normenv[k] = os.environ[k].encode('mbcs') +                normenv[k] = os.environ[k]      # This shouldn't be necessary, since the default environment should include system32,      # but keep this here to be safe, since it's needed to find reg.exe which the MSVC      # bat scripts use. -    sys32_dir = os.path.join(os.environ.get("SystemRoot", os.environ.get("windir",r"C:\Windows\system32")),"System32") +    sys32_dir = os.path.join(os.environ.get("SystemRoot", +                                            os.environ.get("windir", r"C:\Windows\system32")), +                             "System32")      if sys32_dir not in normenv['PATH']:          normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_dir +    # Without Wbem in PATH, vcvarsall.bat has a "'wmic' is not recognized" +    # error starting with Visual Studio 2017, although the script still +    # seems to work anyway. +    sys32_wbem_dir = os.path.join(sys32_dir, 'Wbem') +    if sys32_wbem_dir not in normenv['PATH']: +        normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_wbem_dir +      debug("PATH: %s"%normenv['PATH'])      return normenv @@ -144,11 +153,13 @@ def get_output(vcbat, args = None, env = None):      # execution to work.  This list should really be either directly      # controlled by vc.py, or else derived from the common_tools_var      # settings in vs.py. -    vars = [ +    vs_vc_vars = [          'COMSPEC', -# VS100 and VS110: Still set, but modern MSVC setup scripts will -# discard these if registry has values.  However Intel compiler setup -# script still requires these as of 2013/2014. +        # VS100 and VS110: Still set, but modern MSVC setup scripts will +        # discard these if registry has values.  However Intel compiler setup +        # script still requires these as of 2013/2014. +        'VS140COMNTOOLS', +        'VS120COMNTOOLS',          'VS110COMNTOOLS',          'VS100COMNTOOLS',          'VS90COMNTOOLS', @@ -157,22 +168,22 @@ def get_output(vcbat, args = None, env = None):          'VS70COMNTOOLS',          'VS60COMNTOOLS',      ] -    env['ENV'] = normalize_env(env['ENV'], vars, force=False) +    env['ENV'] = normalize_env(env['ENV'], vs_vc_vars, force=False)      if args:          debug("Calling '%s %s'" % (vcbat, args))          popen = SCons.Action._subproc(env, -                                     '"%s" %s & set' % (vcbat, args), -                                     stdin = 'devnull', -                                     stdout=subprocess.PIPE, -                                     stderr=subprocess.PIPE) +                                      '"%s" %s & set' % (vcbat, args), +                                      stdin='devnull', +                                      stdout=subprocess.PIPE, +                                      stderr=subprocess.PIPE)      else:          debug("Calling '%s'" % vcbat)          popen = SCons.Action._subproc(env, -                                     '"%s" & set' % vcbat, -                                     stdin = 'devnull', -                                     stdout=subprocess.PIPE, -                                     stderr=subprocess.PIPE) +                                      '"%s" & set' % vcbat, +                                      stdin='devnull', +                                      stdout=subprocess.PIPE, +                                      stderr=subprocess.PIPE)      # Use the .stdout and .stderr attributes directly because the      # .communicate() method uses the threading module on Windows @@ -195,10 +206,14 @@ def get_output(vcbat, args = None, env = None):      output = stdout.decode("mbcs")      return output -def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): +def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH")): +    """ +    Parse output from running visual c++/studios vcvarsall.bat and running set +    To capture the values listed in keep +    """ +      # dkeep is a dict associating key: path_list, where key is one item from      # keep, and pat_list the associated list of paths -      dkeep = dict([(i, []) for i in keep])      # rdk will  keep the regex to match the .bat file output line starts @@ -207,22 +222,21 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")):          rdk[i] = re.compile('%s=(.*)' % i, re.I)      def add_env(rmatch, key, dkeep=dkeep): -        plist = rmatch.group(1).split(os.pathsep) -        for p in plist: +        path_list = rmatch.group(1).split(os.pathsep) +        for path in path_list:              # Do not add empty paths (when a var ends with ;) -            if p: -                p = p.encode('mbcs') +            if path:                  # XXX: For some reason, VC98 .bat file adds "" around the PATH                  # values, and it screws up the environment later, so we strip                  # it. -                p = p.strip('"') -                dkeep[key].append(p) +                path = path.strip('"') +                dkeep[key].append(str(path))      for line in output.splitlines(): -        for k,v in rdk.items(): -            m = v.match(line) -            if m: -                add_env(m, k) +        for k, value in rdk.items(): +            match = value.match(line) +            if match: +                add_env(match, k)      return dkeep diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index 8d39cf6..b769c44 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """  """ @@ -29,7 +29,7 @@ import os  import re  import SCons.Util -from common import read_reg, debug +from .common import read_reg, debug  # Original value recorded by dcournapeau  _FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot' @@ -40,13 +40,13 @@ def find_framework_root():      # XXX: find it from environment (FrameworkDir)      try:          froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) -        debug("Found framework install root in registry: %s" % froot) -    except SCons.Util.WinError, e: -        debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) +        debug("Found framework install root in registry: {}".format(froot)) +    except SCons.Util.WinError as e: +        debug("Could not read reg key {}".format(_FRAMEWORKDIR_HKEY_ROOT))          return None      if not os.path.exists(froot): -        debug("%s not found on fs" % froot) +        debug("{} not found on fs".format(froot))          return None      return froot diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 53bb8aa..8bc9830 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """Module to detect the Platform/Windows SDK @@ -33,7 +33,7 @@ import os  import SCons.Errors  import SCons.Util -import common +from . import common  debug = common.debug @@ -76,23 +76,23 @@ class SDKDefinition(object):              return None          hkey = self.HKEY_FMT % self.hkey_data -        debug('find_sdk_dir(): checking registry:%s'%hkey) +        debug('find_sdk_dir(): checking registry:{}'.format(hkey))          try:              sdk_dir = common.read_reg(hkey) -        except SCons.Util.WinError, e: -            debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) +        except SCons.Util.WinError as e: +            debug('find_sdk_dir(): no SDK registry key {}'.format(repr(hkey)))              return None -        debug('find_sdk_dir(): Trying SDK Dir: %s'%sdk_dir) +        debug('find_sdk_dir(): Trying SDK Dir: {}'.format(sdk_dir))          if not os.path.exists(sdk_dir): -            debug('find_sdk_dir():  %s not on file system' % sdk_dir) +            debug('find_sdk_dir():  {} not on file system'.format(sdk_dir))              return None          ftc = os.path.join(sdk_dir, self.sanity_check_file)          if not os.path.exists(ftc): -            debug("find_sdk_dir(): sanity check %s not found" % ftc) +            debug("find_sdk_dir(): sanity check {} not found".format(ftc))              return None          return sdk_dir @@ -105,7 +105,7 @@ class SDKDefinition(object):              sdk_dir = self.find_sdk_dir()              self._sdk_dir = sdk_dir              return sdk_dir -         +      def get_sdk_vc_script(self,host_arch, target_arch):          """ Return the script to initialize the VC compiler installed by SDK          """ @@ -113,11 +113,11 @@ class SDKDefinition(object):          if (host_arch == 'amd64' and target_arch == 'x86'):              # No cross tools needed compiling 32 bits on 64 bit machine              host_arch=target_arch -         +          arch_string=target_arch          if (host_arch != target_arch):              arch_string='%s_%s'%(host_arch,target_arch) -             +          debug("sdk.py: get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string,                                                             host_arch,                                                             target_arch)) @@ -164,6 +164,12 @@ SDK70VCSetupScripts =    { 'x86'      : r'bin\vcvars32.bat',                             'x86_ia64' : r'bin\vcvarsx86_ia64.bat',                             'ia64'     : r'bin\vcvarsia64.bat'} +SDK100VCSetupScripts =    {'x86'      : r'bin\vcvars32.bat', +                           'amd64'    : r'bin\vcvars64.bat', +                           'x86_amd64': r'bin\x86_amd64\vcvarsx86_amd64.bat', +                           'x86_arm'  : r'bin\x86_arm\vcvarsx86_arm.bat'} + +  # The list of support SDKs which we know how to detect.  #  # The first SDK found in the list is the one used by default if there @@ -172,6 +178,16 @@ SDK70VCSetupScripts =    { 'x86'      : r'bin\vcvars32.bat',  #  # If you update this list, update the documentation in Tool/mssdk.xml.  SupportedSDKList = [ +    WindowsSDK('10.0', +               sanity_check_file=r'bin\SetEnv.Cmd', +               include_subdir='include', +               lib_subdir={ +                   'x86'       : ['lib'], +                   'x86_64'    : [r'lib\x64'], +                   'ia64'      : [r'lib\ia64'], +               }, +               vc_setup_scripts = SDK70VCSetupScripts, +              ),      WindowsSDK('7.1',                 sanity_check_file=r'bin\SetEnv.Cmd',                 include_subdir='include', @@ -308,8 +324,7 @@ def set_sdk_by_directory(env, sdk_dir):  def get_sdk_by_version(mssdk):      if mssdk not in SupportedSDKMap: -        msg = "SDK version %s is not supported" % repr(mssdk) -        raise SCons.Errors.UserError(msg) +        raise SCons.Errors.UserError("SDK version {} is not supported".format(repr(mssdk)))      get_installed_sdks()      return InstalledSDKMap.get(mssdk) @@ -327,16 +342,16 @@ def mssdk_setup_env(env):          if sdk_dir is None:              return          sdk_dir = env.subst(sdk_dir) -        debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:%s'%sdk_dir) +        debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:{}'.format(sdk_dir))      elif 'MSSDK_VERSION' in env:          sdk_version = env['MSSDK_VERSION']          if sdk_version is None: -            msg = "SDK version is specified as None"   +            msg = "SDK version is specified as None"              raise SCons.Errors.UserError(msg)          sdk_version = env.subst(sdk_version)          mssdk = get_sdk_by_version(sdk_version)          if mssdk is None: -            msg = "SDK version %s is not installed" % sdk_version  +            msg = "SDK version %s is not installed" % sdk_version              raise SCons.Errors.UserError(msg)          sdk_dir = mssdk.get_sdk_dir()          debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) @@ -347,7 +362,7 @@ def mssdk_setup_env(env):              debug('sdk.py:mssdk_setup_env thinks msvs_version is None')              return          msvs_version = env.subst(msvs_version) -        import vs +        from . import vs          msvs = vs.get_vs_by_version(msvs_version)          debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs)          if not msvs: diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index ca8a2da..fba86af 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -30,24 +30,25 @@  #   * test on 64 bits XP +  VS 2005 (and VS 6 if possible)  #   * SDK  #   * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """Module for Visual C/C++ detection and configuration.  """  import SCons.compat  import SCons.Util +import subprocess  import os  import platform  from string import digits as string_digits  import SCons.Warnings -import common +from . import common  debug = common.debug -import sdk +from . import sdk  get_installed_sdks = sdk.get_installed_sdks @@ -108,7 +109,7 @@ def get_host_target(env):          # PROCESSOR_ARCHITECTURE.          if not host_platform:              host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '') -             +      # Retain user requested TARGET_ARCH      req_target_platform = env.get('TARGET_ARCH')      debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform) @@ -118,26 +119,28 @@ def get_host_target(env):          target_platform = req_target_platform      else:          target_platform = host_platform -         +      try:          host = _ARCH_TO_CANONICAL[host_platform.lower()] -    except KeyError, e: +    except KeyError as e:          msg = "Unrecognized host architecture %s"          raise ValueError(msg % repr(host_platform))      try:          target = _ARCH_TO_CANONICAL[target_platform.lower()] -    except KeyError, e: -        all_archs = str(_ARCH_TO_CANONICAL.keys()) +    except KeyError as e: +        all_archs = str(list(_ARCH_TO_CANONICAL.keys()))          raise ValueError("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs))      return (host, target,req_target_platform)  # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the  # MSVC_VERSION documentation in Tool/msvc.xml. -_VCVER = ["14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] +_VCVER = ["14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"]  _VCVER_TO_PRODUCT_DIR = { +    '14.1' : [ +        (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # Visual Studio 2017 doesn't set this registry key anymore      '14.0' : [          (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')],      '14.0Exp' : [ @@ -183,19 +186,19 @@ _VCVER_TO_PRODUCT_DIR = {          (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'),          ]  } -         +  def msvc_version_to_maj_min(msvc_version): -   msvc_version_numeric = ''.join([x for  x in msvc_version if x in string_digits + '.']) - -   t = msvc_version_numeric.split(".") -   if not len(t) == 2: -       raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) -   try: -       maj = int(t[0]) -       min = int(t[1]) -       return maj, min -   except ValueError, e: -       raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) +    msvc_version_numeric = ''.join([x for  x in msvc_version if x in string_digits + '.']) + +    t = msvc_version_numeric.split(".") +    if not len(t) == 2: +        raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) +    try: +        maj = int(t[0]) +        min = int(t[1]) +        return maj, min +    except ValueError as e: +        raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))  def is_host_target_supported(host_target, msvc_version):      """Return True if the given (host, target) tuple is supported given the @@ -222,6 +225,35 @@ def is_host_target_supported(host_target, msvc_version):      return True + +def find_vc_pdir_vswhere(msvc_version): +    """ +    Find the MSVC product directory using vswhere.exe . +    Run it asking for specified version and get MSVS  install location +    :param msvc_version: +    :return: MSVC install dir +    """ +    vswhere_path = os.path.join( +        'C:\\', +        'Program Files (x86)', +        'Microsoft Visual Studio', +        'Installer', +        'vswhere.exe' +    ) +    vswhere_cmd = [vswhere_path, '-version', msvc_version, '-property', 'installationPath'] + +    if os.path.exists(vswhere_path): +        sp = subprocess.Popen(vswhere_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +        vsdir, err = sp.communicate() +        vsdir = vsdir.decode("mbcs") +        vsdir = vsdir.rstrip() +        vc_pdir = os.path.join(vsdir, 'VC') +        return vc_pdir +    else: +        # No vswhere on system, no install info available +        return None + +  def find_vc_pdir(msvc_version):      """Try to find the product directory for the given      version. @@ -240,26 +272,31 @@ def find_vc_pdir(msvc_version):      for hkroot, key in hkeys:          try:              comps = None -            if common.is_win64(): -                try: -                    # ordinally at win64, try Wow6432Node first. -                    comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) -                except SCons.Util.WinError, e: -                    # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node -                    pass -            if not comps: -                # not Win64, or Microsoft Visual Studio for Python 2.7 -                comps = common.read_reg(root + key, hkroot) -        except SCons.Util.WinError, e: -            debug('find_vc_dir(): no VC registry key %s' % repr(key)) +            if not key: +                comps = find_vc_pdir_vswhere(msvc_version) +                if not comps: +                    debug('find_vc_dir(): no VC found via vswhere for version {}'.format(repr(key))) +                    raise SCons.Util.WinError +            else: +                if common.is_win64(): +                    try: +                        # ordinally at win64, try Wow6432Node first. +                        comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) +                    except SCons.Util.WinError as e: +                        # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node +                        pass +                if not comps: +                    # not Win64, or Microsoft Visual Studio for Python 2.7 +                    comps = common.read_reg(root + key, hkroot) +        except SCons.Util.WinError as e: +            debug('find_vc_dir(): no VC registry key {}'.format(repr(key)))          else: -            debug('find_vc_dir(): found VC in registry: %s' % comps) +            debug('find_vc_dir(): found VC in registry: {}'.format(comps))              if os.path.exists(comps):                  return comps              else: -                debug('find_vc_dir(): reg says dir is %s, but it does not exist. (ignoring)'\ -                          % comps) -                raise MissingConfiguration("registry dir %s not found on the filesystem" % comps) +                debug('find_vc_dir(): reg says dir is {}, but it does not exist. (ignoring)'.format(comps)) +                raise MissingConfiguration("registry dir {} not found on the filesystem".format(comps))      return None  def find_batch_file(env,msvc_version,host_arch,target_arch): @@ -270,8 +307,8 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):      pdir = find_vc_pdir(msvc_version)      if pdir is None:          raise NoVersionFound("No version of Visual Studio found") -         -    debug('vc.py: find_batch_file() pdir:%s'%pdir) + +    debug('vc.py: find_batch_file() pdir:{}'.format(pdir))      # filter out e.g. "Exp" from the version name      msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."]) @@ -282,13 +319,15 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):      elif vernum < 7:          pdir = os.path.join(pdir, "Bin")          batfilename = os.path.join(pdir, "vcvars32.bat") -    else: # >= 8 +    elif 8 <= vernum <= 14:          batfilename = os.path.join(pdir, "vcvarsall.bat") +    else:  # vernum >= 14.1  VS2017 and above +        batfilename = os.path.join(pdir, "Auxiliary", "Build", "vcvarsall.bat")      if not os.path.exists(batfilename):          debug("Not found: %s" % batfilename)          batfilename = None -     +      installed_sdks=get_installed_sdks()      for _sdk in installed_sdks:          sdk_bat_file = _sdk.get_sdk_vc_script(host_arch,target_arch) @@ -296,7 +335,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):              debug("vc.py:find_batch_file() not found:%s"%_sdk)          else:              sdk_bat_file_path = os.path.join(pdir,sdk_bat_file) -            if os.path.exists(sdk_bat_file_path):  +            if os.path.exists(sdk_bat_file_path):                  debug('vc.py:find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path)                  return (batfilename,sdk_bat_file_path)      return (batfilename,None) @@ -323,7 +362,7 @@ def get_installed_vcs():                  installed_versions.append(ver)              else:                  debug('find_vc_pdir return None for ver %s' % ver) -        except VisualCException, e: +        except VisualCException as e:              debug('did not find VC %s: caught exception %s' % (ver, str(e)))      return installed_versions @@ -359,7 +398,7 @@ def get_default_version(env):      msvc_version = env.get('MSVC_VERSION')      msvs_version = env.get('MSVS_VERSION') -     +      debug('get_default_version(): msvc_version:%s msvs_version:%s'%(msvc_version,msvs_version))      if msvs_version and not msvc_version: @@ -409,7 +448,7 @@ def msvc_find_valid_batch_script(env,version):      try_target_archs = [target_platform]      debug("msvs_find_valid_batch_script(): req_target_platform %s target_platform:%s"%(req_target_platform,target_platform)) -    # VS2012 has a "cross compile" environment to build 64 bit  +    # VS2012 has a "cross compile" environment to build 64 bit      # with x86_amd64 as the argument to the batch setup script      if req_target_platform in ('amd64','x86_64'):          try_target_archs.append('x86_amd64') @@ -427,7 +466,7 @@ def msvc_find_valid_batch_script(env,version):      for tp in try_target_archs:          # Set to current arch.          env['TARGET_ARCH']=tp -         +          debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp)          host_target = (host_platform, tp)          if not is_host_target_supported(host_target, version): @@ -436,11 +475,19 @@ def msvc_find_valid_batch_script(env,version):              SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)          arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] +        # Get just version numbers +        maj, min = msvc_version_to_maj_min(version) +        # VS2015+ +        if maj >= 14: +            if env.get('MSVC_UWP_APP') == '1': +                # Initialize environment variables with store/universal paths +                arg += ' store' +          # Try to locate a batch file for this host/target platform combo          try:              (vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp)              debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) -        except VisualCException, e: +        except VisualCException as e:              msg = str(e)              debug('Caught exception while looking for batch file (%s)' % msg)              warn_msg = "VC version %s not installed.  " + \ @@ -449,13 +496,13 @@ def msvc_find_valid_batch_script(env,version):              warn_msg = warn_msg % (version, cached_get_installed_vcs())              SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)              continue -         +          # Try to use the located batch file for this host/target platform combo          debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg))          if vc_script:              try:                  d = script_env(vc_script, args=arg) -            except BatchFileExecutionError, e: +            except BatchFileExecutionError as e:                  debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e))                  vc_script=None                  continue @@ -463,23 +510,23 @@ def msvc_find_valid_batch_script(env,version):              debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script))              try:                  d = script_env(sdk_script) -            except BatchFileExecutionError,e: +            except BatchFileExecutionError as e:                  debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e))                  continue          elif not vc_script and not sdk_script:              debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found')              continue -         +          debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s %s"%(repr(sdk_script),arg))          break # We've found a working target_platform, so stop looking -     +      # If we cannot find a viable installed compiler, reset the TARGET_ARCH      # To it's initial value      if not d:          env['TARGET_ARCH']=req_target_platform -     +      return d -     +  def msvc_setup_env(env):      debug('msvc_setup_env()') @@ -498,12 +545,12 @@ def msvc_setup_env(env):      env['MSVS_VERSION'] = version      env['MSVS'] = {} -     +      use_script = env.get('MSVC_USE_SCRIPT', True)      if SCons.Util.is_String(use_script):          debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script))          d = script_env(use_script) -    elif use_script:       +    elif use_script:          d = msvc_find_valid_batch_script(env,version)          debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d)          if not d: @@ -524,4 +571,3 @@ def msvc_exists(version=None):      if version is None:          return len(vcs) > 0      return version in vcs -     diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index 1f04cbe..dafdbaf 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -1,5 +1,5 @@  # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  # -__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"  __doc__ = """Module to detect Visual Studio and/or Visual C/C++  """ @@ -31,7 +31,7 @@ import os  import SCons.Errors  import SCons.Util -from common import debug, \ +from .common import debug, \                     get_output, \                     is_win64, \                     normalize_env, \ @@ -83,10 +83,10 @@ class VisualStudio(object):              key = root + key              try:                  comps = read_reg(key) -            except SCons.Util.WinError, e: -                debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) +            except SCons.Util.WinError as e: +                debug('find_vs_dir_by_reg(): no VS registry key {}'.format(repr(key)))              else: -                debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) +                debug('find_vs_dir_by_reg(): found VS in registry: {}'.format(comps))                  return comps          return None @@ -105,12 +105,12 @@ class VisualStudio(object):      def find_executable(self):          vs_dir = self.get_vs_dir()          if not vs_dir: -            debug('find_executable():  no vs_dir (%s)'%vs_dir) +            debug('find_executable():  no vs_dir ({})'.format(vs_dir))              return None          executable = os.path.join(vs_dir, self.executable_path)          executable = os.path.normpath(executable)          if not os.path.isfile(executable): -            debug('find_executable():  %s not on file system' % executable) +            debug('find_executable():  {} not on file system'.format(executable))              return None          return executable @@ -199,17 +199,28 @@ class VisualStudio(object):  # Tool/MSCommon/vc.py, and the MSVC_VERSION documentation in Tool/msvc.xml.  SupportedVSList = [ +    # Visual Studio 2017 +    VisualStudio('14.1', +                 vc_version='14.1', +                 sdk_version='10.0A', +                 hkeys=[], +                 common_tools_var='VS150COMNTOOLS', +                 executable_path=r'Common7\IDE\devenv.com', +                 batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat', +                 supported_arch=['x86', 'amd64', "arm"], +                 ), +      # Visual Studio 2015      VisualStudio('14.0',                   vc_version='14.0', -                 sdk_version='10.0A', +                 sdk_version='10.0',                   hkeys=[r'Microsoft\VisualStudio\14.0\Setup\VS\ProductDir'],                   common_tools_var='VS140COMNTOOLS',                   executable_path=r'Common7\IDE\devenv.com',                   batch_file_path=r'Common7\Tools\vsvars32.bat',                   supported_arch=['x86', 'amd64', "arm"],      ), -  +      # Visual C++ 2015 Express Edition (for Desktop)      VisualStudio('14.0Exp',                   vc_version='14.0',  | 
