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 |