"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py" (8 Mar 2017, 17165 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # Copyright (c) 2013 Google Inc. All rights reserved.
    2 # Use of this source code is governed by a BSD-style license that can be
    3 # found in the LICENSE file.
    4 
    5 """Handle version information related to Visual Stuio."""
    6 
    7 import errno
    8 import os
    9 import re
   10 import subprocess
   11 import sys
   12 import gyp
   13 import glob
   14 
   15 
   16 class VisualStudioVersion(object):
   17   """Information regarding a version of Visual Studio."""
   18 
   19   def __init__(self, short_name, description,
   20                solution_version, project_version, flat_sln, uses_vcxproj,
   21                path, sdk_based, default_toolset=None):
   22     self.short_name = short_name
   23     self.description = description
   24     self.solution_version = solution_version
   25     self.project_version = project_version
   26     self.flat_sln = flat_sln
   27     self.uses_vcxproj = uses_vcxproj
   28     self.path = path
   29     self.sdk_based = sdk_based
   30     self.default_toolset = default_toolset
   31 
   32   def ShortName(self):
   33     return self.short_name
   34 
   35   def Description(self):
   36     """Get the full description of the version."""
   37     return self.description
   38 
   39   def SolutionVersion(self):
   40     """Get the version number of the sln files."""
   41     return self.solution_version
   42 
   43   def ProjectVersion(self):
   44     """Get the version number of the vcproj or vcxproj files."""
   45     return self.project_version
   46 
   47   def FlatSolution(self):
   48     return self.flat_sln
   49 
   50   def UsesVcxproj(self):
   51     """Returns true if this version uses a vcxproj file."""
   52     return self.uses_vcxproj
   53 
   54   def ProjectExtension(self):
   55     """Returns the file extension for the project."""
   56     return self.uses_vcxproj and '.vcxproj' or '.vcproj'
   57 
   58   def Path(self):
   59     """Returns the path to Visual Studio installation."""
   60     return self.path
   61 
   62   def ToolPath(self, tool):
   63     """Returns the path to a given compiler tool. """
   64     return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
   65 
   66   def DefaultToolset(self):
   67     """Returns the msbuild toolset version that will be used in the absence
   68     of a user override."""
   69     return self.default_toolset
   70 
   71   def SetupScript(self, target_arch):
   72     """Returns a command (with arguments) to be used to set up the
   73     environment."""
   74     # Check if we are running in the SDK command line environment and use
   75     # the setup script from the SDK if so. |target_arch| should be either
   76     # 'x86' or 'x64'.
   77     assert target_arch in ('x86', 'x64')
   78     sdk_dir = os.environ.get('WindowsSDKDir')
   79     if self.sdk_based and sdk_dir:
   80       return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
   81               '/' + target_arch]
   82     else:
   83       # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls
   84       # vcvars32, which it can only find if VS??COMNTOOLS is set, which it
   85       # isn't always.
   86       if target_arch == 'x86':
   87         if self.short_name >= '2013' and self.short_name[-1] != 'e' and (
   88             os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
   89             os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
   90           # VS2013 and later, non-Express have a x64-x86 cross that we want
   91           # to prefer.
   92           return [os.path.normpath(
   93              os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86']
   94         # Otherwise, the standard x86 compiler.
   95         return [os.path.normpath(
   96           os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))]
   97       else:
   98         assert target_arch == 'x64'
   99         arg = 'x86_amd64'
  100         # Use the 64-on-64 compiler if we're not using an express
  101         # edition and we're running on a 64bit OS.
  102         if self.short_name[-1] != 'e' and (
  103             os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
  104             os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
  105           arg = 'amd64'
  106         return [os.path.normpath(
  107             os.path.join(self.path, 'VC/vcvarsall.bat')), arg]
  108 
  109 
  110 def _RegistryQueryBase(sysdir, key, value):
  111   """Use reg.exe to read a particular key.
  112 
  113   While ideally we might use the win32 module, we would like gyp to be
  114   python neutral, so for instance cygwin python lacks this module.
  115 
  116   Arguments:
  117     sysdir: The system subdirectory to attempt to launch reg.exe from.
  118     key: The registry key to read from.
  119     value: The particular value to read.
  120   Return:
  121     stdout from reg.exe, or None for failure.
  122   """
  123   # Skip if not on Windows or Python Win32 setup issue
  124   if sys.platform not in ('win32', 'cygwin'):
  125     return None
  126   # Setup params to pass to and attempt to launch reg.exe
  127   cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
  128          'query', key]
  129   if value:
  130     cmd.extend(['/v', value])
  131   p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  132   # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
  133   # Note that the error text may be in [1] in some cases
  134   text = p.communicate()[0]
  135   # Check return code from reg.exe; officially 0==success and 1==error
  136   if p.returncode:
  137     return None
  138   return text
  139 
  140 
  141 def _RegistryQuery(key, value=None):
  142   r"""Use reg.exe to read a particular key through _RegistryQueryBase.
  143 
  144   First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
  145   that fails, it falls back to System32.  Sysnative is available on Vista and
  146   up and available on Windows Server 2003 and XP through KB patch 942589. Note
  147   that Sysnative will always fail if using 64-bit python due to it being a
  148   virtual directory and System32 will work correctly in the first place.
  149 
  150   KB 942589 - http://support.microsoft.com/kb/942589/en-us.
  151 
  152   Arguments:
  153     key: The registry key.
  154     value: The particular registry value to read (optional).
  155   Return:
  156     stdout from reg.exe, or None for failure.
  157   """
  158   text = None
  159   try:
  160     text = _RegistryQueryBase('Sysnative', key, value)
  161   except OSError, e:
  162     if e.errno == errno.ENOENT:
  163       text = _RegistryQueryBase('System32', key, value)
  164     else:
  165       raise
  166   return text
  167 
  168 
  169 def _RegistryGetValueUsingWinReg(key, value):
  170   """Use the _winreg module to obtain the value of a registry key.
  171 
  172   Args:
  173     key: The registry key.
  174     value: The particular registry value to read.
  175   Return:
  176     contents of the registry key's value, or None on failure.  Throws
  177     ImportError if _winreg is unavailable.
  178   """
  179   import _winreg
  180   try:
  181     root, subkey = key.split('\\', 1)
  182     assert root == 'HKLM'  # Only need HKLM for now.
  183     with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
  184       return _winreg.QueryValueEx(hkey, value)[0]
  185   except WindowsError:
  186     return None
  187 
  188 
  189 def _RegistryGetValue(key, value):
  190   """Use _winreg or reg.exe to obtain the value of a registry key.
  191 
  192   Using _winreg is preferable because it solves an issue on some corporate
  193   environments where access to reg.exe is locked down. However, we still need
  194   to fallback to reg.exe for the case where the _winreg module is not available
  195   (for example in cygwin python).
  196 
  197   Args:
  198     key: The registry key.
  199     value: The particular registry value to read.
  200   Return:
  201     contents of the registry key's value, or None on failure.
  202   """
  203   try:
  204     return _RegistryGetValueUsingWinReg(key, value)
  205   except ImportError:
  206     pass
  207 
  208   # Fallback to reg.exe if we fail to import _winreg.
  209   text = _RegistryQuery(key, value)
  210   if not text:
  211     return None
  212   # Extract value.
  213   match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
  214   if not match:
  215     return None
  216   return match.group(1)
  217 
  218 
  219 def _CreateVersion(name, path, sdk_based=False):
  220   """Sets up MSVS project generation.
  221 
  222   Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
  223   autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
  224   passed in that doesn't match a value in versions python will throw a error.
  225   """
  226   if path:
  227     path = os.path.normpath(path)
  228   versions = {
  229       '2015': VisualStudioVersion('2015',
  230                                   'Visual Studio 2015',
  231                                   solution_version='12.00',
  232                                   project_version='14.0',
  233                                   flat_sln=False,
  234                                   uses_vcxproj=True,
  235                                   path=path,
  236                                   sdk_based=sdk_based,
  237                                   default_toolset='v140'),
  238       '2013': VisualStudioVersion('2013',
  239                                   'Visual Studio 2013',
  240                                   solution_version='13.00',
  241                                   project_version='12.0',
  242                                   flat_sln=False,
  243                                   uses_vcxproj=True,
  244                                   path=path,
  245                                   sdk_based=sdk_based,
  246                                   default_toolset='v120'),
  247       '2013e': VisualStudioVersion('2013e',
  248                                    'Visual Studio 2013',
  249                                    solution_version='13.00',
  250                                    project_version='12.0',
  251                                    flat_sln=True,
  252                                    uses_vcxproj=True,
  253                                    path=path,
  254                                    sdk_based=sdk_based,
  255                                    default_toolset='v120'),
  256       '2012': VisualStudioVersion('2012',
  257                                   'Visual Studio 2012',
  258                                   solution_version='12.00',
  259                                   project_version='4.0',
  260                                   flat_sln=False,
  261                                   uses_vcxproj=True,
  262                                   path=path,
  263                                   sdk_based=sdk_based,
  264                                   default_toolset='v110'),
  265       '2012e': VisualStudioVersion('2012e',
  266                                    'Visual Studio 2012',
  267                                    solution_version='12.00',
  268                                    project_version='4.0',
  269                                    flat_sln=True,
  270                                    uses_vcxproj=True,
  271                                    path=path,
  272                                    sdk_based=sdk_based,
  273                                    default_toolset='v110'),
  274       '2010': VisualStudioVersion('2010',
  275                                   'Visual Studio 2010',
  276                                   solution_version='11.00',
  277                                   project_version='4.0',
  278                                   flat_sln=False,
  279                                   uses_vcxproj=True,
  280                                   path=path,
  281                                   sdk_based=sdk_based),
  282       '2010e': VisualStudioVersion('2010e',
  283                                    'Visual C++ Express 2010',
  284                                    solution_version='11.00',
  285                                    project_version='4.0',
  286                                    flat_sln=True,
  287                                    uses_vcxproj=True,
  288                                    path=path,
  289                                    sdk_based=sdk_based),
  290       '2008': VisualStudioVersion('2008',
  291                                   'Visual Studio 2008',
  292                                   solution_version='10.00',
  293                                   project_version='9.00',
  294                                   flat_sln=False,
  295                                   uses_vcxproj=False,
  296                                   path=path,
  297                                   sdk_based=sdk_based),
  298       '2008e': VisualStudioVersion('2008e',
  299                                    'Visual Studio 2008',
  300                                    solution_version='10.00',
  301                                    project_version='9.00',
  302                                    flat_sln=True,
  303                                    uses_vcxproj=False,
  304                                    path=path,
  305                                    sdk_based=sdk_based),
  306       '2005': VisualStudioVersion('2005',
  307                                   'Visual Studio 2005',
  308                                   solution_version='9.00',
  309                                   project_version='8.00',
  310                                   flat_sln=False,
  311                                   uses_vcxproj=False,
  312                                   path=path,
  313                                   sdk_based=sdk_based),
  314       '2005e': VisualStudioVersion('2005e',
  315                                    'Visual Studio 2005',
  316                                    solution_version='9.00',
  317                                    project_version='8.00',
  318                                    flat_sln=True,
  319                                    uses_vcxproj=False,
  320                                    path=path,
  321                                    sdk_based=sdk_based),
  322   }
  323   return versions[str(name)]
  324 
  325 
  326 def _ConvertToCygpath(path):
  327   """Convert to cygwin path if we are using cygwin."""
  328   if sys.platform == 'cygwin':
  329     p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
  330     path = p.communicate()[0].strip()
  331   return path
  332 
  333 
  334 def _DetectVisualStudioVersions(versions_to_check, force_express):
  335   """Collect the list of installed visual studio versions.
  336 
  337   Returns:
  338     A list of visual studio versions installed in descending order of
  339     usage preference.
  340     Base this on the registry and a quick check if devenv.exe exists.
  341     Only versions 8-10 are considered.
  342     Possibilities are:
  343       2005(e) - Visual Studio 2005 (8)
  344       2008(e) - Visual Studio 2008 (9)
  345       2010(e) - Visual Studio 2010 (10)
  346       2012(e) - Visual Studio 2012 (11)
  347       2013(e) - Visual Studio 2013 (12)
  348       2015    - Visual Studio 2015 (14)
  349     Where (e) is e for express editions of MSVS and blank otherwise.
  350   """
  351   version_to_year = {
  352       '8.0': '2005',
  353       '9.0': '2008',
  354       '10.0': '2010',
  355       '11.0': '2012',
  356       '12.0': '2013',
  357       '14.0': '2015',
  358   }
  359   versions = []
  360   for version in versions_to_check:
  361     # Old method of searching for which VS version is installed
  362     # We don't use the 2010-encouraged-way because we also want to get the
  363     # path to the binaries, which it doesn't offer.
  364     keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
  365             r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
  366             r'HKLM\Software\Microsoft\VCExpress\%s' % version,
  367             r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
  368     for index in range(len(keys)):
  369       path = _RegistryGetValue(keys[index], 'InstallDir')
  370       if not path:
  371         continue
  372       path = _ConvertToCygpath(path)
  373       # Check for full.
  374       full_path = os.path.join(path, 'devenv.exe')
  375       express_path = os.path.join(path, '*express.exe')
  376       if not force_express and os.path.exists(full_path):
  377         # Add this one.
  378         versions.append(_CreateVersion(version_to_year[version],
  379             os.path.join(path, '..', '..')))
  380       # Check for express.
  381       elif glob.glob(express_path):
  382         # Add this one.
  383         versions.append(_CreateVersion(version_to_year[version] + 'e',
  384             os.path.join(path, '..', '..')))
  385 
  386     # The old method above does not work when only SDK is installed.
  387     keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7',
  388             r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7']
  389     for index in range(len(keys)):
  390       path = _RegistryGetValue(keys[index], version)
  391       if not path:
  392         continue
  393       path = _ConvertToCygpath(path)
  394       if version != '14.0':  # There is no Express edition for 2015.
  395         versions.append(_CreateVersion(version_to_year[version] + 'e',
  396             os.path.join(path, '..'), sdk_based=True))
  397 
  398   return versions
  399 
  400 
  401 def SelectVisualStudioVersion(version='auto', allow_fallback=True):
  402   """Select which version of Visual Studio projects to generate.
  403 
  404   Arguments:
  405     version: Hook to allow caller to force a particular version (vs auto).
  406   Returns:
  407     An object representing a visual studio project format version.
  408   """
  409   # In auto mode, check environment variable for override.
  410   if version == 'auto':
  411     version = os.environ.get('GYP_MSVS_VERSION', 'auto')
  412   version_map = {
  413     'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'),
  414     '2005': ('8.0',),
  415     '2005e': ('8.0',),
  416     '2008': ('9.0',),
  417     '2008e': ('9.0',),
  418     '2010': ('10.0',),
  419     '2010e': ('10.0',),
  420     '2012': ('11.0',),
  421     '2012e': ('11.0',),
  422     '2013': ('12.0',),
  423     '2013e': ('12.0',),
  424     '2015': ('14.0',),
  425   }
  426   override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH')
  427   if override_path:
  428     msvs_version = os.environ.get('GYP_MSVS_VERSION')
  429     if not msvs_version:
  430       raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be '
  431                        'set to a particular version (e.g. 2010e).')
  432     return _CreateVersion(msvs_version, override_path, sdk_based=True)
  433   version = str(version)
  434   versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
  435   if not versions:
  436     if not allow_fallback:
  437       raise ValueError('Could not locate Visual Studio installation.')
  438     if version == 'auto':
  439       # Default to 2005 if we couldn't find anything
  440       return _CreateVersion('2005', None)
  441     else:
  442       return _CreateVersion(version, None)
  443   return versions[0]