Permalink
Browse files

Clone of: http://codereview.chromium.org/6729005/

Landing for rnorton
Review URL: http://codereview.chromium.org/6900057

git-svn-id: http://gyp.googlecode.com/svn/trunk@915 78cadc50-ecff-11dd-a971-7dbc132099af
  • Loading branch information...
1 parent 645b7d8 commit de15c1afebfaa3577368a0636c547b48b0b98812 bradnelson@google.com committed Apr 25, 2011
Showing with 107 additions and 43 deletions.
  1. +1 −0 AUTHORS
  2. +106 −43 pylib/gyp/MSVSVersion.py
View
@@ -3,3 +3,4 @@
Google Inc.
Steven Knight <knight@baldmt.com>
+Ryan Norton <rnorton10@gmail.com>
View
@@ -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 @@ def ProjectExtension(self):
"""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,24 +133,31 @@ def _RegistryKeyExists(key):
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',
solution_version='11.00',
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,37 +195,48 @@ def _DetectVisualStudioVersions():
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 = []
# For now, prefer versions before VS2010
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

0 comments on commit de15c1a

Please sign in to comment.