summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Tool/msvc.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Tool/msvc.py')
-rw-r--r--src/engine/SCons/Tool/msvc.py320
1 files changed, 225 insertions, 95 deletions
diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py
index 6f0c516..f936535 100644
--- a/src/engine/SCons/Tool/msvc.py
+++ b/src/engine/SCons/Tool/msvc.py
@@ -35,59 +35,121 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import string
+import types
+import re
import SCons.Action
import SCons.Tool
import SCons.Errors
+import SCons.Warnings
import SCons.Builder
import SCons.Util
import SCons.Platform.win32
+import SCons.Tool.msvs
CSuffixes = ['.c', '.C']
CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
-def get_devstudio_versions():
- """
- Get list of devstudio versions from the Windows registry. Return a
- list of strings containing version numbers; an exception will be raised
- if we were unable to access the registry (eg. couldn't import
- a registry-access module) or the appropriate registry keys weren't
- found.
- """
-
+def _parse_msvc7_overrides(version):
+ """ Parse any overridden defaults for MSVS directory locations in MSVS .NET. """
+
+ # First, we get the shell folder for this user:
if not SCons.Util.can_read_reg:
raise SCons.Errors.InternalError, "No Windows registry module was found"
- K = 'Software\\Microsoft\\Devstudio'
- L = []
- for base in (SCons.Util.HKEY_CLASSES_ROOT,
- SCons.Util.HKEY_LOCAL_MACHINE,
- SCons.Util.HKEY_CURRENT_USER,
- SCons.Util.HKEY_USERS):
+ comps = ""
+ try:
+ (comps, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
+ r'Software\Microsoft\Windows\CurrentVersion' +\
+ r'\Explorer\Shell Folders\Local AppData')
+ except SCons.Util.RegError:
+ raise SCons.Errors.InternalError, "The Local AppData directory was not found in the registry."
+
+ comps = comps + '\\Microsoft\\VisualStudio\\' + version + '\\VSComponents.dat'
+ dirs = {}
+
+ if os.path.exists(comps):
+ # now we parse the directories from this file, if it exists.
+ # We only look for entries after: [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories],
+ # since this file could contain a number of things...
+ f = open(comps,'r')
+ line = f.readline()
+ found = 0
+ while line:
+ line.strip()
+ if found == 1:
+ (key, val) = line.split('=',1)
+ key = key.replace(' Dirs','')
+ dirs[key.upper()] = val
+ if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories]') >= 0:
+ found = 1
+ if line == '':
+ found = 0
+ line = f.readline()
+ f.close()
+ else:
+ # since the file didn't exist, we have only the defaults in
+ # the registry to work with.
try:
- k = SCons.Util.RegOpenKeyEx(base,K)
+ K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version
+ K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories'
+ k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K)
i = 0
while 1:
try:
- p = SCons.Util.RegEnumKey(k,i)
- if p[0] in '123456789' and p not in L:
- L.append(p)
+ (key,val,t) = SCons.Util.RegEnumValue(k,i)
+ key = key.replace(' Dirs','')
+ dirs[key.upper()] = val
+ i = i + 1
except SCons.Util.RegError:
break
- i = i + 1
except SCons.Util.RegError:
- pass
+ # if we got here, then we didn't find the registry entries:
+ raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
+ return dirs
+
+def _get_msvc7_path(path, version, platform):
+ """
+ Get Visual Studio directories from version 7 (MSVS .NET)
+ (it has a different registry structure than versions before it)
+ """
+ # first, look for a customization of the default values in the
+ # registry: These are sometimes stored in the Local Settings area
+ # for Visual Studio, in a file, so we have to parse it.
+ dirs = _parse_msvc7_overrides(version)
+
+ if dirs.has_key(path):
+ p = dirs[path]
+ else:
+ raise SCons.Errors.InternalError, "Unable to retrieve the %s path from MS VC++."%path
+
+ # collect some useful information for later expansions...
+ paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+
+ # expand the directory path variables that we support. If there
+ # is a variable we don't support, then replace that entry with
+ # "---Unknown Location VSInstallDir---" or something similar, to clue
+ # people in that we didn't find something, and so env expansion doesn't
+ # do weird things with the $(xxx)'s
+ s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
+
+ def repl(match):
+ key = string.upper(match.group(1))
+ if paths.has_key(key):
+ return paths[key]
+ else:
+ return '---Unknown Location %s---' % match.group()
- if not L:
- raise SCons.Errors.InternalError, "DevStudio was not found."
+ rv = []
+ for entry in p.split(os.pathsep):
+ entry = s.sub(repl,entry)
+ rv.append(entry)
- L.sort()
- L.reverse()
- return L
+ return string.join(rv,os.pathsep)
def get_msvc_path (path, version, platform='x86'):
"""
- Get a list of devstudio directories (include, lib or path). Return
+ Get a list of visualstudio directories (include, lib or path). Return
a string delimited by ';'. An exception will be raised if unable to
access the registry or appropriate registry keys not found.
"""
@@ -95,16 +157,22 @@ def get_msvc_path (path, version, platform='x86'):
if not SCons.Util.can_read_reg:
raise SCons.Errors.InternalError, "No Windows registry module was found"
- if path=='lib':
- path= 'Library'
+ # normalize the case for comparisons (since the registry is case
+ # insensitive)
+ path = string.upper(path)
+
+ if path=='LIB':
+ path= 'LIBRARY'
+
+ if float(version) >= 7.0:
+ return _get_msvc7_path(path, version, platform)
+
path = string.upper(path + ' Dirs')
K = ('Software\\Microsoft\\Devstudio\\%s\\' +
'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
(version,platform)
- for base in (SCons.Util.HKEY_CLASSES_ROOT,
- SCons.Util.HKEY_LOCAL_MACHINE,
- SCons.Util.HKEY_CURRENT_USER,
- SCons.Util.HKEY_USERS):
+ for base in (SCons.Util.HKEY_CURRENT_USER,
+ SCons.Util.HKEY_LOCAL_MACHINE):
try:
k = SCons.Util.RegOpenKeyEx(base,K)
i = 0
@@ -120,77 +188,127 @@ def get_msvc_path (path, version, platform='x86'):
pass
# if we got here, then we didn't find the registry entries:
- raise SCons.Errors.InternalError, "%s was not found in the registry."%path
-
-def get_msdev_dir(version):
- """Returns the root directory of the MSDev installation from the
- registry if it can be found, otherwise we guess."""
- if SCons.Util.can_read_reg:
- K = ('Software\\Microsoft\\Devstudio\\%s\\' +
- 'Products\\Microsoft Visual C++') % \
- version
- for base in (SCons.Util.HKEY_LOCAL_MACHINE,
- SCons.Util.HKEY_CURRENT_USER):
- try:
- k = SCons.Util.RegOpenKeyEx(base,K)
- val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
- return os.path.split(val)[0]
- except SCons.Util.RegError:
- pass
-
-def get_msdev_paths(version=None):
+ raise SCons.Errors.InternalError, "The %s path was not found in the registry."%path
+
+def _get_msvc6_default_paths(version):
+ """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+ three environment variables that should be set in order to execute
+ the MSVC 6.0 tools properly, if the information wasn't available
+ from the registry."""
+ MVSdir = None
+ paths = {}
+ exe_path = ''
+ lib_path = ''
+ include_path = ''
+ try:
+ paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+ MVSdir = paths['VSINSTALLDIR']
+ except (SCons.Util.RegError, SCons.Errors.InternalError):
+ if os.environ.has_key('MSDEVDIR'):
+ MVSdir = os.path.normpath(os.path.join(os.environ['MSDEVDIR'],'..','..'))
+ else:
+ MVSdir = r'C:\Program Files\Microsoft Visual Studio'
+ if MVSdir:
+ if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
+ MVSVCdir = paths['VCINSTALLDIR']
+ else:
+ MVSVCdir = os.path.join(MVSdir,'VC98')
+
+ MVSCommondir = r'%s\Common' % MVSdir
+ include_path = r'%s\ATL\include;%s\MFC\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir)
+ lib_path = r'%s\MFC\lib;%s\lib' % (MVSVCdir, MVSVCdir)
+ exe_path = r'%s\MSDev98\bin;%s\bin' % (MVSCommondir, MVSVCdir)
+ return (include_path, lib_path, exe_path)
+
+def _get_msvc7_default_paths(version):
+ """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+ three environment variables that should be set in order to execute
+ the MSVC .NET tools properly, if the information wasn't available
+ from the registry."""
+
+ MVSdir = None
+ paths = {}
+ exe_path = ''
+ lib_path = ''
+ include_path = ''
+ try:
+ paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+ MVSdir = paths['VSINSTALLDIR']
+ except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
+ if os.environ.has_key('VSCOMNTOOLS'):
+ MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
+ else:
+ # last resort -- default install location
+ MVSdir = r'C:\Program Files\Microsoft Visual Studio .NET'
+
+ if not MVSdir:
+ if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
+ MVSVCdir = paths['VCINSTALLDIR']
+ else:
+ MVSVCdir = os.path.join(MVSdir,'Vc7')
+
+ MVSCommondir = r'%s\Common7' % MVSdir
+ include_path = r'%s\atlmfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir)
+ lib_path = r'%s\atlmfc\lib;%s\lib' % (MVSVCdir, MVSVCdir)
+ exe_path = r'%s\Tools\bin;%s\Tools;%s\bin' % (MVSCommondir, MVSCommondir, MVSVCdir)
+ return (include_path, lib_path, exe_path)
+
+def get_msvc_paths(version=None):
"""Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
of those three environment variables that should be set
in order to execute the MSVC tools properly."""
exe_path = ''
lib_path = ''
include_path = ''
+
+ if not version and not SCons.Util.can_read_reg:
+ version = '6.0'
+
try:
if not version:
- version = get_devstudio_versions()[0] #use highest version
+ version = get_visualstudio_versions()[0] #use highest version
+
include_path = get_msvc_path("include", version)
lib_path = get_msvc_path("lib", version)
- exe_path = get_msvc_path("path", version) + ";" + os.environ['PATH']
+ exe_path = get_msvc_path("path", version)
+
except (SCons.Util.RegError, SCons.Errors.InternalError):
- # Could not get the configured directories from the registry.
- # However, the configured directories only appear if the user
- # changes them from the default. Therefore, we'll see if
- # we can get the path to the MSDev base installation from
- # the registry and deduce the default directories.
- MVSdir = None
- if version:
- MVSdir = get_msdev_dir(version)
- if MVSdir:
- MVSVCdir = r'%s\VC98' % MVSdir
- MVSCommondir = r'%s\Common' % MVSdir
- include_path = r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir)
- lib_path = r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir)
- try:
- extra_path = os.pathsep + os.environ['PATH']
- except KeyError:
- extra_path = ''
- exe_path = (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path
+ # Could not get all the configured directories from the
+ # registry. However, some of the configured directories only
+ # appear if the user changes them from the default.
+ # Therefore, we'll see if we can get the path to the MSDev
+ # base installation from the registry and deduce the default
+ # directories.
+ if float(version) >= 7.0:
+ return _get_msvc7_default_paths(version)
else:
- # The DevStudio environment variables don't exist,
- # so just use the variables from the source environment.
- progfiles = SCons.Platform.win32.get_program_files_dir()
- MVSdir = os.path.join(progfiles,r'Microsoft Visual Studio')
- MVSVCdir = r'%s\VC98' % MVSdir
- MVSCommondir = r'%s\Common' % MVSdir
- try:
- include_path = os.environ['INCLUDE']
- except KeyError:
- include_path = ''
- try:
- lib_path = os.environ['LIB']
- except KeyError:
- lib_path = ''
- try:
- exe_path = os.environ['PATH']
- except KeyError:
- exe_path = ''
+ return _get_msvc6_default_paths(version)
+
return (include_path, lib_path, exe_path)
+def get_msvc_default_paths(version = None):
+ """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+ three environment variables that should be set in order to execute
+ the MSVC tools properly. This will only return the default
+ locations for the tools, not the values used by MSVS in their
+ directory setup area. This can help avoid problems with different
+ developers having different settings, and should allow the tools
+ to run in most cases."""
+
+ if not version and not SCons.Util.can_read_reg:
+ version = '6.0'
+
+ try:
+ if not version:
+ version = get_visualstudio_versions()[0] #use highest version
+ except:
+ pass
+
+ if float(version) >= 7.0:
+ return _get_msvc7_default_paths(version)
+ else:
+ return _get_msvc6_default_paths(version)
+
def validate_vars(env):
"""Validate the PDB, PCH, and PCHSTOP construction variables."""
if env.has_key('PCH') and env['PCH']:
@@ -282,10 +400,18 @@ def generate(env):
CScan.add_skey('.rc')
env['BUILDERS']['RES'] = res_builder
- if SCons.Util.can_read_reg:
- include_path, lib_path, exe_path = get_msdev_paths()
- env['ENV']['INCLUDE'] = include_path
- env['ENV']['PATH'] = exe_path
+ version = SCons.Tool.msvs.get_default_visualstudio_version(env)
+
+ if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']:
+ include_path, lib_path, exe_path = get_msvc_default_paths(version)
+ else:
+ include_path, lib_path, exe_path = get_msvc_paths(version)
+
+ # since other tools can set these, we just make sure that the
+ # relevant stuff from MSVS is in there somewhere.
+ env.PrependENVPath('INCLUDE', include_path)
+ env.PrependENVPath('LIB', lib_path)
+ env.PrependENVPath('PATH', exe_path)
env['CFILESUFFIX'] = '.c'
env['CXXFILESUFFIX'] = '.cc'
@@ -294,4 +420,8 @@ def generate(env):
env['BUILDERS']['PCH'] = pch_builder
def exists(env):
- return env.Detect('cl')
+ if not SCons.Util.can_read_reg or not SCons.Tool.msvs.get_visualstudio_versions():
+ return env.Detect('cl')
+ else:
+ # there's at least one version of MSVS installed.
+ return True