| Index: pylib/gyp/MSVSVersion.py
|
| ===================================================================
|
| --- pylib/gyp/MSVSVersion.py (revision 912)
|
| +++ pylib/gyp/MSVSVersion.py (working copy)
|
| @@ -1,11 +1,11 @@
|
| #!/usr/bin/python
|
| -
|
| -# Copyright (c) 2009 Google Inc. All rights reserved.
|
| +# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| """Handle version information related to Visual Stuio."""
|
|
|
| +import errno
|
| import os
|
| import re
|
| import subprocess
|
| @@ -50,36 +50,81 @@
|
| """Returns the file extension for the project."""
|
| return self.uses_vcxproj and '.vcxproj' or '.vcproj'
|
|
|
| -def _RegistryGetValue(key, value):
|
| - """Use reg.exe to read a paricular key.
|
| +def _RegistryQueryBase(sysdir, key, value):
|
| + """Use reg.exe to read a particular key.
|
|
|
| While ideally we might use the win32 module, we would like gyp to be
|
| python neutral, so for instance cygwin python lacks this module.
|
|
|
| Arguments:
|
| + sysdir: The system subdirectory to attempt to launch reg.exe from.
|
| key: The registry key to read from.
|
| value: The particular value to read.
|
| Return:
|
| - The contents there, or None for failure.
|
| + stdout from reg.exe, or None for failure.
|
| """
|
| - # Skip if not on Windows.
|
| + # Skip if not on Windows or Python Win32 setup issue
|
| if sys.platform not in ('win32', 'cygwin'):
|
| return None
|
| - # Run reg.exe.
|
| - cmd = [os.path.join(os.environ.get('WINDIR', ''), 'System32', 'reg.exe'),
|
| - 'query', key, '/v', value]
|
| + # Setup params to pass to and attempt to launch reg.exe
|
| + cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
|
| + 'query', key]
|
| + if value:
|
| + cmd.extend(['/v', value])
|
| p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| + # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
|
| + # Note that the error text may be in [1] in some cases
|
| text = p.communicate()[0]
|
| - # Require a successful return value.
|
| + # Check return code from reg.exe; officially 0==success and 1==error
|
| if p.returncode:
|
| return None
|
| + return text
|
| +
|
| +def _RegistryQuery(key, value=None):
|
| + """Use reg.exe to read a particular key through _RegistryQueryBase.
|
| +
|
| + First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
|
| + that fails, it falls back to System32. Sysnative is available on Vista and
|
| + up and available on Windows Server 2003 and XP through KB patch 942589. Note
|
| + that Sysnative will always fail if using 64-bit python due to it being a
|
| + virtual directory and System32 will work correctly in the first place.
|
| +
|
| + KB 942589 - http://support.microsoft.com/kb/942589/en-us.
|
| +
|
| + Arguments:
|
| + key: The registry key.
|
| + value: The particular registry value to read (optional).
|
| + Return:
|
| + stdout from reg.exe, or None for failure.
|
| + """
|
| + text = None
|
| + try:
|
| + text = _RegistryQueryBase('Sysnative', key, value)
|
| + except OSError, e:
|
| + if e.errno == errno.ENOENT:
|
| + text = _RegistryQueryBase('System32', key, value)
|
| + else:
|
| + raise
|
| + return text
|
| +
|
| +def _RegistryGetValue(key, value):
|
| + """Use reg.exe to obtain the value of a registry key.
|
| +
|
| + Args:
|
| + key: The registry key.
|
| + value: The particular registry value to read.
|
| + Return:
|
| + contents of the registry key's value, or None on failure.
|
| + """
|
| + text = _RegistryQuery(key, value)
|
| + if not text:
|
| + return None
|
| # Extract value.
|
| match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
|
| if not match:
|
| return None
|
| return match.group(1)
|
|
|
| -
|
| def _RegistryKeyExists(key):
|
| """Use reg.exe to see if a key exists.
|
|
|
| @@ -88,17 +133,18 @@
|
| Return:
|
| True if the key exists
|
| """
|
| - # Skip if not on Windows.
|
| - if sys.platform not in ('win32', 'cygwin'):
|
| - return None
|
| - # Run reg.exe.
|
| - cmd = [os.path.join(os.environ.get('WINDIR', ''), 'System32', 'reg.exe'),
|
| - 'query', key]
|
| - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| - return p.returncode == 0
|
| + if not _RegistryQuery(key):
|
| + return False
|
| + return True
|
|
|
|
|
| def _CreateVersion(name):
|
| + """Sets up MSVS project generation.
|
| +
|
| + Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
|
| + autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
|
| + passed in that doesn't match a value in versions python will throw a error.
|
| + """
|
| versions = {
|
| '2010': VisualStudioVersion('2010',
|
| 'Visual Studio 2010',
|
| @@ -106,6 +152,12 @@
|
| project_version='4.0',
|
| flat_sln=False,
|
| uses_vcxproj=True),
|
| + '2010e': VisualStudioVersion('2010e',
|
| + 'Visual Studio 2010',
|
| + solution_version='11.00',
|
| + project_version='4.0',
|
| + flat_sln=True,
|
| + uses_vcxproj=True),
|
| '2008': VisualStudioVersion('2008',
|
| 'Visual Studio 2008',
|
| solution_version='10.00',
|
| @@ -143,9 +195,10 @@
|
| Base this on the registry and a quick check if devenv.exe exists.
|
| Only versions 8-10 are considered.
|
| Possibilities are:
|
| - 2005 - Visual Studio 2005 (8)
|
| - 2008 - Visual Studio 2008 (9)
|
| - 2010 - Visual Studio 2010 (10)
|
| + 2005(e) - Visual Studio 2005 (8)
|
| + 2008(e) - Visual Studio 2008 (9)
|
| + 2010(e) - Visual Studio 2010 (10)
|
| + Where (e) is e for express editions of MSVS and blank otherwise.
|
| """
|
| version_to_year = {'8.0': '2005', '9.0': '2008', '10.0': '2010'}
|
| versions = []
|
| @@ -153,27 +206,37 @@
|
| for version in ('9.0', '8.0', '10.0'):
|
| # Check if VS2010 and later is installed as specified by
|
| # http://msdn.microsoft.com/en-us/library/bb164659.aspx
|
| - key32 = r'HKLM\SOFTWARE\Microsoft\DevDiv\VS\Servicing\%s' % version
|
| - key64 = r'HKLM\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\%sD' % (
|
| - version)
|
| - if _RegistryKeyExists(key32) or _RegistryKeyExists(key64):
|
| - # Add this one.
|
| - # TODO(jeanluc) This does not check for an express version.
|
| - versions.append(_CreateVersion(version_to_year[version]))
|
| - continue
|
| - # Get the install dir for this version.
|
| - key = r'HKLM\Software\Microsoft\VisualStudio\%s' % version
|
| - path = _RegistryGetValue(key, 'InstallDir')
|
| - if not path:
|
| - continue
|
| - # Check for full.
|
| - if os.path.exists(os.path.join(path, 'devenv.exe')):
|
| - # Add this one.
|
| - versions.append(_CreateVersion(version_to_year[version]))
|
| - # Check for express.
|
| - elif os.path.exists(os.path.join(path, 'vcexpress.exe')):
|
| - # Add this one.
|
| - versions.append(_CreateVersion(version_to_year[version] + 'e'))
|
| + keys = [r'HKLM\SOFTWARE\Microsoft\DevDiv\VS\Servicing\%s' % version,
|
| + r'HKLM\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\%s' % (
|
| + version)]
|
| + for index in range(len(keys)):
|
| + if not _RegistryKeyExists(keys[index]):
|
| + continue
|
| + # Check for express
|
| + if _RegistryKeyExists(keys[index] + '\expbsln'):
|
| + # Add this one
|
| + versions.append(_CreateVersion(version_to_year[version] + 'e'))
|
| + else:
|
| + # Add this one
|
| + versions.append(_CreateVersion(version_to_year[version]))
|
| +
|
| + # Old (pre-VS2010) method of searching for which VS version is installed
|
| + keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
|
| + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
|
| + r'HKLM\Software\Microsoft\VCExpress\%s' % version,
|
| + r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
|
| + for index in range(len(keys)):
|
| + path = _RegistryGetValue(keys[index], 'InstallDir')
|
| + if not path:
|
| + continue
|
| + # Check for full.
|
| + if os.path.exists(os.path.join(path, 'devenv.exe')):
|
| + # Add this one.
|
| + versions.append(_CreateVersion(version_to_year[version]))
|
| + # Check for express.
|
| + elif os.path.exists(os.path.join(path, 'vcexpress.exe')):
|
| + # Add this one.
|
| + versions.append(_CreateVersion(version_to_year[version] + 'e'))
|
| return versions
|
|
|
|
|
|
|