diff options
Diffstat (limited to 'src/engine/SCons/Tool/MSCommon')
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/__init__.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/arch.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/common.py | 62 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/netframework.py | 10 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/sdk.py | 22 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py | 182 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py.bak | 394 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vs.py | 36 |
8 files changed, 196 insertions, 516 deletions
diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index a612d9b..6389078 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py 5023 2010/06/14 22:05:46 scons" __doc__ = """ Common functions for Microsoft Visual Studio and Visual C/C++. diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py index 34de46c..ba6d2d6 100644 --- a/src/engine/SCons/Tool/MSCommon/arch.py +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -21,14 +21,14 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py 5023 2010/06/14 22:05:46 scons" __doc__ = """Module to define supported Windows chip architectures. """ import os -class ArchDefinition: +class ArchDefinition(object): """ A class for defining architecture-specific settings and logic. """ diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 2303d2b..ef1aae9 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py 5023 2010/06/14 22:05:46 scons" __doc__ = """ Common helper functions for working with the Microsoft tool chain. @@ -99,46 +99,78 @@ def has_reg(value): # Functions for fetching environment variable settings from batch files. -def normalize_env(env, keys): +def normalize_env(env, keys, force=False): """Given a dictionary representing a shell environment, add the variables from os.environ needed for the processing of .bat files; the keys are controlled by the keys argument. It also makes sure the environment values are correctly encoded. - Note: the environment is copied""" + If force=True, then all of the key values that exist are copied + into the returned dictionary. If force=false, values are only + copied if the key does not already exist in the copied dictionary. + + Note: the environment is copied.""" normenv = {} if env: for k in env.keys(): normenv[k] = copy.deepcopy(env[k]).encode('mbcs') for k in keys: - if os.environ.has_key(k): + if k in os.environ and (force or not k in normenv): normenv[k] = os.environ[k].encode('mbcs') return normenv def get_output(vcbat, args = None, env = None): """Parse the output of given bat file, with given args.""" + + if env is None: + # Create a blank environment, for use in launching the tools + env = SCons.Environment.Environment(tools=[]) + + # TODO: This is a hard-coded list of the variables that (may) need + # to be imported from os.environ[] for v[sc]*vars*.bat file + # execution to work. This list should really be either directly + # controlled by vc.py, or else derived from the common_tools_var + # settings in vs.py. + vars = [ + 'COMSPEC', + 'VS90COMNTOOLS', + 'VS80COMNTOOLS', + 'VS71COMNTOOLS', + 'VS70COMNTOOLS', + 'VS60COMNTOOLS', + ] + env['ENV'] = normalize_env(env['ENV'], vars, force=False) + if args: debug("Calling '%s %s'" % (vcbat, args)) - popen = subprocess.Popen('"%s" %s & set' % (vcbat, args), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) + popen = SCons.Action._subproc(env, + '"%s" %s & set' % (vcbat, args), + stdin = 'devnull', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) else: debug("Calling '%s'" % vcbat) - popen = subprocess.Popen('"%s" & set' % vcbat, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) + popen = SCons.Action._subproc(env, + '"%s" & set' % vcbat, + stdin = 'devnull', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # Use the .stdout and .stderr attributes directly because the # .communicate() method uses the threading module on Windows # and won't work under Pythons not built with threading. stdout = popen.stdout.read() + stderr = popen.stderr.read() + if stderr: + # TODO: find something better to do with stderr; + # this at least prevents errors from getting swallowed. + import sys + sys.stderr.write(stderr) if popen.wait() != 0: - raise IOError(popen.stderr.read().decode("mbcs")) + raise IOError(stderr.decode("mbcs")) output = stdout.decode("mbcs") return output @@ -147,9 +179,7 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): # dkeep is a dict associating key: path_list, where key is one item from # keep, and pat_list the associated list of paths - # TODO(1.5): replace with the following list comprehension: - #dkeep = dict([(i, []) for i in keep]) - dkeep = dict(map(lambda i: (i, []), keep)) + dkeep = dict([(i, []) for i in keep]) # rdk will keep the regex to match the .bat file output line starts rdk = {} diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index bd123dc..30be811 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -19,16 +19,14 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py 5023 2010/06/14 22:05:46 scons" __doc__ = """ """ import os import re -import string from common import read_reg, debug @@ -58,14 +56,14 @@ def query_versions(): contents = os.listdir(froot) l = re.compile('v[0-9]+.*') - versions = filter(lambda e, l=l: l.match(e), contents) + versions = [e for e in contents if l.match(e)] def versrt(a,b): # since version numbers aren't really floats... aa = a[1:] bb = b[1:] - aal = string.split(aa, '.') - bbl = string.split(bb, '.') + aal = aa.split('.') + bbl = bb.split('.') # sequence comparison in python is lexicographical # which is exactly what we want. # Note we sort backwards so the highest version is first. diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 54be8ca..6debeb6 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py 5023 2010/06/14 22:05:46 scons" __doc__ = """Module to detect the Platform/Windows SDK @@ -58,7 +58,7 @@ _CURINSTALLED_SDK_HKEY_ROOT = \ r"Software\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder" -class SDKDefinition: +class SDKDefinition(object): """ An abstract base class for trying to find installed SDK directories. """ @@ -131,7 +131,7 @@ class WindowsSDK(SDKDefinition): """ HKEY_FMT = r'Software\Microsoft\Microsoft SDKs\Windows\v%s\InstallationFolder' def __init__(self, *args, **kw): - apply(SDKDefinition.__init__, (self,)+args, kw) + SDKDefinition.__init__(self, *args, **kw) self.hkey_data = self.version class PlatformSDK(SDKDefinition): @@ -140,7 +140,7 @@ class PlatformSDK(SDKDefinition): """ HKEY_FMT = r'Software\Microsoft\MicrosoftSDK\InstalledSDKS\%s\Install Dir' def __init__(self, *args, **kw): - apply(SDKDefinition.__init__, (self,)+args, kw) + SDKDefinition.__init__(self, *args, **kw) self.hkey_data = self.uuid # @@ -310,9 +310,9 @@ def get_cur_sdk_dir_from_reg(): return val def get_sdk_by_version(mssdk): - if not SupportedSDKMap.has_key(mssdk): + if mssdk not in SupportedSDKMap: msg = "SDK version %s is not supported" % repr(mssdk) - raise SCons.Errors.UserError, msg + raise SCons.Errors.UserError(msg) get_installed_sdks() return InstalledSDKMap.get(mssdk) @@ -328,22 +328,22 @@ def get_default_sdk(): def mssdk_setup_env(env): debug('sdk.py:mssdk_setup_env()') - if env.has_key('MSSDK_DIR'): + if 'MSSDK_DIR' in env: sdk_dir = env['MSSDK_DIR'] if sdk_dir is None: return sdk_dir = env.subst(sdk_dir) debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:%s'%sdk_dir) - elif env.has_key('MSSDK_VERSION'): + elif 'MSSDK_VERSION' in env: sdk_version = env['MSSDK_VERSION'] if sdk_version is None: msg = "SDK version %s is not installed" % repr(mssdk) - raise SCons.Errors.UserError, msg + raise SCons.Errors.UserError(msg) sdk_version = env.subst(sdk_version) mssdk = get_sdk_by_version(sdk_version) sdk_dir = mssdk.get_sdk_dir() debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) - elif env.has_key('MSVS_VERSION'): + elif 'MSVS_VERSION' in env: msvs_version = env['MSVS_VERSION'] debug('sdk.py:mssdk_setup_env:Getting MSVS_VERSION from env:%s'%msvs_version) if msvs_version is None: @@ -382,7 +382,7 @@ def mssdk_exists(version=None): sdks = get_installed_sdks() if version is None: return len(sdks) > 0 - return sdks.has_key(version) + return version in sdks # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 5ea5a53..f07f34c 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -30,15 +30,15 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py 5023 2010/06/14 22:05:46 scons" __doc__ = """Module for Visual C/C++ detection and configuration. """ import SCons.compat -import string import os import platform +from string import digits as string_digits import SCons.Warnings @@ -71,13 +71,16 @@ class BatchFileExecutionError(VisualCException): # Dict to 'canonalize' the arch _ARCH_TO_CANONICAL = { - "x86": "x86", - "amd64": "amd64", - "i386": "x86", - "emt64": "amd64", - "x86_64": "amd64", - "itanium": "ia64", - "ia64": "ia64", + "amd64" : "amd64", + "emt64" : "amd64", + "i386" : "x86", + "i486" : "x86", + "i586" : "x86", + "i686" : "x86", + "ia64" : "ia64", + "itanium" : "ia64", + "x86" : "x86", + "x86_64" : "amd64", } # Given a (host, target) tuple, return the argument for the bat file. Both host @@ -91,6 +94,8 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = { } def get_host_target(env): + debug('vc.py:get_host_target()') + host_platform = env.get('HOST_ARCH') if not host_platform: host_platform = platform.machine() @@ -99,22 +104,29 @@ def get_host_target(env): # PROCESSOR_ARCHITECTURE. if not host_platform: host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '') - target_platform = env.get('TARGET_ARCH') - if not target_platform: + + # Retain user requested TARGET_ARCH + req_target_platform = env.get('TARGET_ARCH') + debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform) + + if req_target_platform: + # If user requested a specific platform then only try that one. + target_platform = req_target_platform + else: target_platform = host_platform - + try: - host = _ARCH_TO_CANONICAL[host_platform] + host = _ARCH_TO_CANONICAL[host_platform.lower()] except KeyError, e: msg = "Unrecognized host architecture %s" raise ValueError(msg % repr(host_platform)) try: - target = _ARCH_TO_CANONICAL[target_platform] + target = _ARCH_TO_CANONICAL[target_platform.lower()] except KeyError, e: raise ValueError("Unrecognized target architecture %s" % target_platform) - return (host, target) + return (host, target,req_target_platform) _VCVER = ["10.0", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] @@ -136,17 +148,19 @@ _VCVER_TO_PRODUCT_DIR = { '6.0': [ r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'] } - + def msvc_version_to_maj_min(msvc_version): - t = msvc_version.split(".") - if not len(t) == 2: - raise ValueError("Unrecognized version %s" % msvc_version) - try: - maj = int(t[0]) - min = int(t[1]) - return maj, min - except ValueError, e: - raise ValueError("Unrecognized version %s" % msvc_version) + msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.']) + + t = msvc_version_numeric.split(".") + if not len(t) == 2: + raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) + try: + maj = int(t[0]) + min = int(t[1]) + return maj, min + except ValueError, e: + raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) def is_host_target_supported(host_target, msvc_version): """Return True if the given (host, target) tuple is supported given the @@ -206,7 +220,7 @@ def find_vc_pdir(msvc_version): raise MissingConfiguration("registry dir %s not found on the filesystem" % comps) return None -def find_batch_file(env,msvc_version): +def find_batch_file(env,msvc_version,host_arch,target_arch): """ Find the location of the batch script which should set up the compiler for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress @@ -218,7 +232,7 @@ def find_batch_file(env,msvc_version): debug('vc.py: find_batch_file() pdir:%s'%pdir) # filter out e.g. "Exp" from the version name - msvc_ver_numeric = string.join(filter(lambda x: x in string.digits + ".", msvc_version), '') + msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."]) vernum = float(msvc_ver_numeric) if 7 <= vernum < 8: pdir = os.path.join(pdir, os.pardir, "Common7", "Tools") @@ -234,7 +248,6 @@ def find_batch_file(env,msvc_version): batfilename = None installed_sdks=get_installed_sdks() - (host_arch,target_arch)=get_host_target(env) for _sdk in installed_sdks: sdk_bat_file=_sdk.get_sdk_vc_script(host_arch,target_arch) sdk_bat_file_path=os.path.join(pdir,sdk_bat_file) @@ -330,6 +343,73 @@ def msvc_setup_env_once(env): msvc_setup_env(env) env["MSVC_SETUP_RUN"] = True +def msvc_find_valid_batch_script(env,version): + debug('vc.py:msvc_find_valid_batch_script()') + # Find the host platform, target platform, and if present the requested + # target platform + (host_platform, target_platform,req_target_platform) = get_host_target(env) + + # If the user hasn't specifically requested a TARGET_ARCH, and + # The TARGET_ARCH is amd64 then also try 32 bits if there are no viable + # 64 bit tools installed + try_target_archs = [target_platform] + if not req_target_platform and target_platform=='amd64': + try_target_archs.append('x86') + + d = None + for tp in try_target_archs: + # Set to current arch. + env['TARGET_ARCH']=tp + + debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp) + host_target = (host_platform, tp) + if not is_host_target_supported(host_target, version): + warn_msg = "host, target = %s not supported for MSVC version %s" % \ + (host_target, version) + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) + arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] + + # Try to locate a batch file for this host/target platform combo + try: + (vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp) + debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) + except VisualCException, e: + msg = str(e) + debug('Caught exception while looking for batch file (%s)' % msg) + warn_msg = "VC version %s not installed. " + \ + "C/C++ compilers are most likely not set correctly.\n" + \ + " Installed versions are: %s" + warn_msg = warn_msg % (version, cached_get_installed_vcs()) + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) + continue + + # Try to use the located batch file for this host/target platform combo + debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg)) + if vc_script: + try: + d = script_env(vc_script, args=arg) + except BatchFileExecutionError, e: + debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) + vc_script=None + if not vc_script and sdk_script: + debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) + try: + d = script_env(sdk_script,args=[]) + except BatchFileExecutionError,e: + debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) + continue + elif not vc_script and not sdk_script: + debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') + continue + + # If we cannot find a viable installed compiler, reset the TARGET_ARCH + # To it's initial value + if not d: + env['TARGET_ARCH']=req_target_platform + + return d + + def msvc_setup_env(env): debug('msvc_setup_env()') @@ -347,50 +427,16 @@ def msvc_setup_env(env): env['MSVS_VERSION'] = version env['MSVS'] = {} - try: - (vc_script,sdk_script) = find_batch_file(env,version) - debug('vc.py:msvc_setup_env() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) - except VisualCException, e: - msg = str(e) - debug('Caught exception while looking for batch file (%s)' % msg) - warn_msg = "VC version %s not installed. " + \ - "C/C++ compilers are most likely not set correctly.\n" + \ - " Installed versions are: %s" - warn_msg = warn_msg % (version, cached_get_installed_vcs()) - SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) - return None - debug('vc.py:msvc_setup_env() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) use_script = env.get('MSVC_USE_SCRIPT', True) if SCons.Util.is_String(use_script): - debug('use_script 1 %s\n' % repr(use_script)) + debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script)) d = script_env(use_script) - elif use_script: - host_platform, target_platform = get_host_target(env) - host_target = (host_platform, target_platform) - if not is_host_target_supported(host_target, version): - warn_msg = "host, target = %s not supported for MSVC version %s" % \ - (host_target, version) - SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) - arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] - debug('use_script 2 %s, args:%s\n' % (repr(vc_script), arg)) - if vc_script: - try: - d = script_env(vc_script, args=arg) - except BatchFileExecutionError, e: - debug('use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) - vc_script=None - if not vc_script and sdk_script: - debug('use_script 4: trying sdk script: %s'%(sdk_script)) - try: - d = script_env(sdk_script,args=[]) - except BatchFileExecutionError,e: - debug('use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) - return None - elif not vc_script and not sdk_script: - debug('use_script 6: Neither VC script nor SDK script found') - return None - + elif use_script: + d = msvc_find_valid_batch_script(env,version) + debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d) + if not d: + return d else: debug('MSVC_USE_SCRIPT set to False') warn_msg = "MSVC_USE_SCRIPT set to False, assuming environment " \ diff --git a/src/engine/SCons/Tool/MSCommon/vc.py.bak b/src/engine/SCons/Tool/MSCommon/vc.py.bak deleted file mode 100644 index 1bdd298..0000000 --- a/src/engine/SCons/Tool/MSCommon/vc.py.bak +++ /dev/null @@ -1,394 +0,0 @@ -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py.bak 4720 2010/03/24 03:14:11 jars" - -__doc__ = """Module for Visual C/C++ detection and configuration. -""" - -import os -import platform - -import SCons.Warnings - -import common - -debug = common.debug - -class VisualC: - """ - An base class for finding installed versions of Visual C/C++. - """ - def __init__(self, version, **kw): - self.version = version - self.__dict__.update(kw) - self._cache = {} - - def vcbin_arch(self): - if common.is_win64(): - result = { - 'x86_64' : ['amd64', r'BIN\x86_amd64'], - 'ia64' : [r'BIN\ia64'], - }.get(target_arch, []) - else: - result = { - 'x86_64' : ['x86_amd64'], - 'ia64' : ['x86_ia64'], - }.get(target_arch, []) - # TODO(1.5) - #return ';'.join(result) - return string.join(result, ';') - - # Support for searching for an appropriate .bat file. - # The map is indexed by (target_architecture, host_architecture). - # Entries where the host_architecture is None specify the - # cross-platform "default" .bat file if there isn't sn entry - # specific to the current host architecture. - - batch_file_map = { - ('x86_64', 'x86_64') : [ - r'bin\amd64\vcvarsamd64.bat', - r'bin\x86_amd64\vcvarsx86_amd64.bat', - r'bin\vcvarsx86_amd64.bat', - ], - ('x86_64', 'x86') : [ - r'bin\x86_amd64\vcvarsx86_amd64.bat', - ], - ('ia64', 'ia64') : [ - r'bin\ia64\vcvarsia64.bat', - r'bin\x86_ia64\vcvarsx86_ia64.bat', - ], - ('ia64', None) : [ - r'bin\x86_ia64\vcvarsx86_ia64.bat', - ], - ('x86', None) : [ - r'bin\vcvars32.bat', - ], - } - - def find_batch_file(self, target_architecture, host_architecture): - key = (target_architecture, host_architecture) - potential_batch_files = self.batch_file_map.get(key) - if not potential_batch_files: - key = (target_architecture, None) - potential_batch_files = self.batch_file_map.get(key) - if potential_batch_files: - product_dir = self.get_vc_dir() - for batch_file in potential_batch_files: - bf = os.path.join(product_dir, batch_file) - if os.path.isfile(bf): - return bf - return None - - def find_vc_dir(self): - root = 'Software\\' - if common.is_win64(): - root = root + 'Wow6432Node\\' - for key in self.hkeys: - key = root + key - try: - comps = common.read_reg(key) - except WindowsError, e: - debug('find_vc_dir(): no VC registry key %s' % repr(key)) - else: - debug('find_vc_dir(): found VC in registry: %s' % comps) - if os.path.exists(comps): - return comps - else: - debug('find_vc_dir(): reg says dir is %s, but it does not exist. (ignoring)'\ - % comps) - return None - return None - - # - - def get_batch_file(self, target_architecture, host_architecture): - try: - return self._cache['batch_file'] - except KeyError: - batch_file = self.find_batch_file(target_architecture, host_architecture) - self._cache['batch_file'] = batch_file - return batch_file - - def get_vc_dir(self): - try: - return self._cache['vc_dir'] - except KeyError: - vc_dir = self.find_vc_dir() - self._cache['vc_dir'] = vc_dir - return vc_dir - - def reset(self): - self._cache={} - - -# The list of supported Visual C/C++ versions we know how to detect. -# -# The first VC found in the list is the one used by default if there -# are multiple VC installed. Barring good reasons to the contrary, -# this means we should list VC with from most recent to oldest. -# -# If you update this list, update the documentation in Tool/vc.xml. -SupportedVCList = [ - VisualC('9.0', - hkeys=[ - r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir', - r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir', - ], - default_install=r'Microsoft Visual Studio 9.0\VC', - common_tools_var='VS90COMNTOOLS', - vc_subdir=r'\VC', - batch_file_base='vcvars', - supported_arch=['x86', 'x86_64', 'ia64'], - atlmc_include_subdir = [r'ATLMFC\INCLUDE'], - atlmfc_lib_subdir = { - 'x86' : r'ATLMFC\LIB', - 'x86_64' : r'ATLMFC\LIB\amd64', - 'ia64' : r'ATLMFC\LIB\ia64', - }, - crt_lib_subdir = { - 'x86_64' : r'LIB\amd64', - 'ia64' : r'LIB\ia64', - }, - ), - VisualC('8.0', - hkeys=[ - r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir', - r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir', - ], - default_install=r'%s\Microsoft Visual Studio 8\VC', - common_tools_var='VS80COMNTOOLS', - vc_subdir=r'\VC', - batch_file_base='vcvars', - supported_arch=['x86', 'x86_64', 'ia64'], - atlmc_include_subdir = [r'ATLMFC\INCLUDE'], - atlmfc_lib_subdir = { - 'x86' : r'ATLMFC\LIB', - 'x86_64' : r'ATLMFC\LIB\amd64', - 'ia64' : r'ATLMFC\LIB\ia64', - }, - crt_lib_subdir = { - 'x86_64' : r'LIB\amd64', - 'ia64' : r'LIB\ia64', - }, - ), - VisualC('7.1', - hkeys=[ - r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir', - ], - default_install=r'%s\Microsoft Visual Studio 7.1.NET 2003\VC7', - common_tools_var='VS71COMNTOOLS', - vc_subdir=r'\VC7', - batch_file_base='vcvars', - supported_arch=['x86'], - atlmc_include_subdir = [r'ATLMFC\INCLUDE'], - atlmfc_lib_subdir = { - 'x86' : r'ATLMFC\LIB', - }, - ), - VisualC('7.0', - hkeys=[ - r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir', - ], - default_install=r'%s\Microsoft Visual Studio .NET\VC7', - common_tools_var='VS70COMNTOOLS', - vc_subdir=r'\VC7', - batch_file_base='vcvars', - supported_arch=['x86'], - atlmc_include_subdir = [r'ATLMFC\INCLUDE'], - atlmfc_lib_subdir = { - 'x86' : r'ATLMFC\LIB', - }, - ), - VisualC('6.0', - hkeys=[ - r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir', - ], - default_install=r'%s\Microsoft Visual Studio\VC98', - common_tools_var='VS60COMNTOOLS', - vc_subdir=r'\VC98', - batch_file_base='vcvars', - supported_arch=['x86'], - atlmc_include_subdir = [r'ATL\INCLUDE', r'MFC\INCLUDE'], - atlmfc_lib_subdir = { - 'x86' : r'MFC\LIB', - }, - ), -] - -SupportedVCMap = {} -for vc in SupportedVCList: - SupportedVCMap[vc.version] = vc - - -# Finding installed versions of Visual C/C++ isn't cheap, because it goes -# not only to the registry but also to the disk to sanity-check that there -# is, in fact, something installed there and that the registry entry isn't -# just stale. Find this information once, when requested, and cache it. - -InstalledVCList = None -InstalledVCMap = None - -def get_installed_vcs(): - global InstalledVCList - global InstalledVCMap - if InstalledVCList is None: - InstalledVCList = [] - InstalledVCMap = {} - for vc in SupportedVCList: - debug('trying to find VC %s' % vc.version) - if vc.get_vc_dir(): - debug('found VC %s' % vc.version) - InstalledVCList.append(vc) - InstalledVCMap[vc.version] = vc - return InstalledVCList - - -def set_vc_by_version(env, msvc): - if not SupportedVCMap.has_key(msvc): - msg = "VC version %s is not supported" % repr(msvc) - raise SCons.Errors.UserError, msg - get_installed_vcs() - vc = InstalledVCMap.get(msvc) - if not vc: - msg = "VC version %s is not installed" % repr(msvc) - raise SCons.Errors.UserError, msg - set_vc_by_directory(env, vc.get_vc_dir()) - -# New stuff - -def script_env(script, args=None): - stdout = common.get_output(script, args) - return common.parse_output(stdout) - -def get_default_version(env): - debug('get_default_version()') - - msvc_version = env.get('MSVC_VERSION') - if not msvc_version: - installed_vcs = get_installed_vcs() - debug('InstalledVCMap:%s'%InstalledVCMap) - if not installed_vcs: - msg = 'No installed VCs' - debug('msv %s\n' % repr(msg)) - SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg) - return None - msvc = installed_vcs[0] - msvc_version = msvc.version - debug('msvc_setup_env: using default installed MSVC version %s\n' % repr(msvc_version)) - - return msvc_version - -# Dict to 'canonalize' the arch -_ARCH_TO_CANONICAL = { - "x86": "x86", - "amd64": "amd64", - "i386": "x86", - "emt64": "amd64", - "x86_64": "amd64" -} - -# Given a (host, target) tuple, return the argument for the bat file. Both host -# and targets should be canonalized. -_HOST_TARGET_ARCH_TO_BAT_ARCH = { - ("x86", "x86"): "x86", - ("x86", "amd64"): "x86_amd64", - ("amd64", "amd64"): "amd64", - ("amd64", "x86"): "x86" -} - -def get_host_target(env): - host_platform = env.get('HOST_ARCH') - if not host_platform: - #host_platform = get_default_host_platform() - host_platform = platform.machine() - target_platform = env.get('TARGET_ARCH') - if not target_platform: - target_platform = host_platform - - return (_ARCH_TO_CANONICAL[host_platform], - _ARCH_TO_CANONICAL[target_platform]) - -def msvc_setup_env_once(env): - try: - has_run = env["MSVC_SETUP_RUN"] - except KeyError: - has_run = False - - if not has_run: - msvc_setup_env(env) - env["MSVC_SETUP_RUN"] = False - -def msvc_setup_env(env): - debug('msvc_setup_env()') - - version = get_default_version(env) - host_platform, target_platform = get_host_target(env) - debug('msvc_setup_env: using specified MSVC version %s\n' % repr(version)) - env['MSVC_VERSION'] = version - - msvc = InstalledVCMap.get(version) - if not msvc: - msg = 'VC version %s not installed' % version - debug('msv %s\n' % repr(msg)) - SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg) - return None - - use_script = env.get('MSVC_USE_SCRIPT', True) - if SCons.Util.is_String(use_script): - debug('use_script 1 %s\n' % repr(use_script)) - d = script_env(use_script) - elif use_script: - # XXX: this is VS 2008 specific, fix this - script = os.path.join(msvc.find_vc_dir(), "vcvarsall.bat") - - arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[(host_platform, target_platform)] - debug('use_script 2 %s, args:%s\n' % (repr(script), arg)) - d = script_env(script, args=arg) - else: - debug('msvc.get_default_env()\n') - d = msvc.get_default_env() - - for k, v in d.items(): - env.PrependENVPath(k, v, delete_existing=True) - -def msvc_exists(version=None): - vcs = get_installed_vcs() - if version is None: - return len(vcs) > 0 - return InstalledVCMap.has_key(version) - - -def reset_installed_vcs(): - global InstalledVCList - global InstalledVCMap - InstalledVCList = None - InstalledVCMap = None - for vc in SupportedVCList: - vc.reset() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index e634a18..06030e2 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py 4720 2010/03/24 03:14:11 jars" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py 5023 2010/06/14 22:05:46 scons" __doc__ = """Module to detect Visual Studio and/or Visual C/C++ """ @@ -40,7 +40,7 @@ from common import debug, \ import SCons.Tool.MSCommon.vc -class VisualStudio: +class VisualStudio(object): """ An abstract base class for trying to find installed versions of Visual Studio. @@ -385,9 +385,9 @@ def get_vs_by_version(msvs): global SupportedVSMap debug('vs.py:get_vs_by_version()') - if not SupportedVSMap.has_key(msvs): + if msvs not in SupportedVSMap: msg = "Visual Studio version %s is not supported" % repr(msvs) - raise SCons.Errors.UserError, msg + raise SCons.Errors.UserError(msg) get_installed_visual_studios() vs = InstalledVSMap.get(msvs) debug('InstalledVSMap:%s'%InstalledVSMap) @@ -415,15 +415,13 @@ def get_default_version(env): version: str the default version. """ - if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']): - # TODO(1.5): - #versions = [vs.version for vs in get_installed_visual_studios()] - versions = map(lambda vs: vs.version, get_installed_visual_studios()) + if 'MSVS' not in env or not SCons.Util.is_Dict(env['MSVS']): + versions = [vs.version for vs in get_installed_visual_studios()] env['MSVS'] = {'VERSIONS' : versions} else: versions = env['MSVS'].get('VERSIONS', []) - if not env.has_key('MSVS_VERSION'): + if 'MSVS_VERSION' not in env: if versions: env['MSVS_VERSION'] = versions[0] #use highest version by default else: @@ -451,7 +449,7 @@ def get_default_arch(env): arch = 'x86' elif not arch in msvs.get_supported_arch(): fmt = "Visual Studio version %s does not support architecture %s" - raise SCons.Errors.UserError, fmt % (env['MSVS_VERSION'], arch) + raise SCons.Errors.UserError(fmt % (env['MSVS_VERSION'], arch)) return arch @@ -473,11 +471,15 @@ def msvs_setup_env(env): vars = ('LIB', 'LIBPATH', 'PATH', 'INCLUDE') msvs_list = get_installed_visual_studios() - # TODO(1.5): - #vscommonvarnames = [ vs.common_tools_var for vs in msvs_list ] - vscommonvarnames = map(lambda vs: vs.common_tools_var, msvs_list) - nenv = normalize_env(env['ENV'], vscommonvarnames + ['COMSPEC']) - output = get_output(batfilename, arch, env=nenv) + vscommonvarnames = [vs.common_tools_var for vs in msvs_list] + save_ENV = env['ENV'] + nenv = normalize_env(env['ENV'], + ['COMSPEC'] + vscommonvarnames, + force=True) + try: + output = get_output(batfilename, arch, env=nenv) + finally: + env['ENV'] = save_ENV vars = parse_output(output, vars) for k, v in vars.items(): @@ -487,9 +489,7 @@ def query_versions(): """Query the system to get available versions of VS. A version is considered when a batfile is found.""" msvs_list = get_installed_visual_studios() - # TODO(1.5) - #versions = [ msvs.version for msvs in msvs_list ] - versions = map(lambda msvs: msvs.version, msvs_list) + versions = [msvs.version for msvs in msvs_list] return versions # Local Variables: |