diff options
33 files changed, 1621 insertions, 1144 deletions
diff --git a/QMTest/TestSConsMSVS.py b/QMTest/TestSConsMSVS.py index 0408b67..8a85b3f 100644 --- a/QMTest/TestSConsMSVS.py +++ b/QMTest/TestSConsMSVS.py @@ -636,31 +636,12 @@ print "self._msvs_versions =", str(env['MSVS']['VERSIONS']) """Returns a full path to the executable (MSDEV or devenv) for the specified version of Visual Studio. """ - common_msdev98_bin_msdev_com = ['Common', 'MSDev98', 'Bin', 'MSDEV.COM'] - common7_ide_devenv_com = ['Common7', 'IDE', 'devenv.com'] - common7_ide_vcexpress_exe = ['Common7', 'IDE', 'VCExpress.exe'] - sub_paths = { - '6.0' : [ - common_msdev98_bin_msdev_com, - ], - '7.0' : [ - common7_ide_devenv_com, - ], - '7.1' : [ - common7_ide_devenv_com, - ], - '8.0' : [ - common7_ide_devenv_com, - common7_ide_vcexpress_exe, - ], - } - from SCons.Tool.msvs import get_msvs_install_dirs - vs_path = get_msvs_install_dirs(version)['VSINSTALLDIR'] - for sp in sub_paths[version]: - p = apply(os.path.join, [vs_path] + sp) - if os.path.exists(p): - return p - return apply(os.path.join, [vs_path] + sub_paths[version][0]) + from SCons.Tool.MSCommon import get_vs_by_version + + msvs = get_vs_by_version(version) + if not msvs: + return None + return msvs.get_executable() # Local Variables: # tab-width:4 diff --git a/doc/man/scons.1 b/doc/man/scons.1 index ba51518..f3988f4 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -1776,6 +1776,7 @@ midl mingw mslib mslink +mssdk msvc msvs mwcc diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6d5aa37..cb7fe8c 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -14,6 +14,15 @@ RELEASE X.X.X - XXX - Make suffix-matching for scanners case-insensitive on Windows. + From David Cournapeau: + + - Change the way SCons finds versions of Visual C/C++ and Visual + Studio to find and use the Microsoft v*vars.bat files. + + From Robert P. J. Day: + + - User's Guide updates. + From Dan Eaton: - Fix generation of Visual Studio 8 project files on x64 platforms. @@ -42,10 +51,6 @@ RELEASE X.X.X - XXX - Spell the Windows environment variables consistently "SystemDrive" and "SystemRoot" instead of "SYSTEMDRIVE" and "SYSTEMROOT". - From Robert P. J. Day: - - - User's Guide updates. - RELEASE 1.2.0.d20090113 - Tue, 13 Jan 2009 02:50:30 -0800 diff --git a/src/engine/MANIFEST-xml.in b/src/engine/MANIFEST-xml.in index f852e92..5a5c9b6 100644 --- a/src/engine/MANIFEST-xml.in +++ b/src/engine/MANIFEST-xml.in @@ -59,6 +59,7 @@ SCons/Tool/midl.xml SCons/Tool/mingw.xml SCons/Tool/mslib.xml SCons/Tool/mslink.xml +SCons/Tool/mssdk.xml SCons/Tool/msvc.xml SCons/Tool/msvs.xml SCons/Tool/mwcc.xml diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 203c4d9..ede9888 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -116,12 +116,18 @@ SCons/Tool/latex.py SCons/Tool/lex.py SCons/Tool/link.py SCons/Tool/linkloc.py +SCons/Tool/MSCommon/__init__.py +SCons/Tool/MSCommon/common.py +SCons/Tool/MSCommon/netframework.py +SCons/Tool/MSCommon/sdk.py +SCons/Tool/MSCommon/vs.py SCons/Tool/m4.py SCons/Tool/masm.py SCons/Tool/midl.py SCons/Tool/mingw.py SCons/Tool/mslib.py SCons/Tool/mslink.py +SCons/Tool/mssdk.py SCons/Tool/msvc.py SCons/Tool/msvs.py SCons/Tool/mwcc.py diff --git a/src/engine/SCons/Errors.py b/src/engine/SCons/Errors.py index fc45279..562cbcf 100644 --- a/src/engine/SCons/Errors.py +++ b/src/engine/SCons/Errors.py @@ -125,6 +125,9 @@ class StopError(Exception): class EnvironmentError(Exception): pass +class MSVCError(IOError): + pass + class ExplicitExit(Exception): def __init__(self, node=None, status=None, *args): self.node = node diff --git a/src/engine/SCons/Platform/PlatformTests.py b/src/engine/SCons/Platform/PlatformTests.py index 4f2e3d9..59d7e71 100644 --- a/src/engine/SCons/Platform/PlatformTests.py +++ b/src/engine/SCons/Platform/PlatformTests.py @@ -33,6 +33,8 @@ import UserDict class Environment(UserDict.UserDict): def Detect(self, cmd): return cmd + def AppendENVPath(self, key, value): + pass class PlatformTestCase(unittest.TestCase): def test_Platform(self): diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 890b925..fb23d5d 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -189,15 +189,16 @@ def escape(x): return '"' + x + '"' # Get the windows system directory name +_system_root = None + def get_system_root(): + global _system_root + if _system_root is not None: + return _system_root + # A resonable default if we can't read the registry - try: - val = os.environ['SystemRoot'] - except KeyError: - val = "C:/WINDOWS" - pass + val = os.environ.get('SystemRoot', "C:/WINDOWS") - # First see if we can look in the registry... if SCons.Util.can_read_reg: try: # Look for Windows NT system root @@ -214,6 +215,7 @@ def get_system_root(): raise except: pass + _system_root = val return val # Get the location of the program files directory @@ -267,9 +269,7 @@ def generate(env): # the env's PATH. The problem with that is that it might not # contain an ENV and a PATH. if not cmd_interp: - systemroot = r'C:\Windows' - if os.environ.has_key('SystemRoot'): - systemroot = os.environ['SystemRoot'] + systemroot = get_system_root() tmp_path = systemroot + os.pathsep + \ os.path.join(systemroot,'System32') tmp_pathext = '.com;.exe;.bat;.cmd' @@ -302,6 +302,13 @@ def generate(env): if v: env['ENV'][var] = v + if not env['ENV'].has_key('COMSPEC'): + v = os.environ.get("COMSPEC") + if v: + env['ENV']['COMSPEC'] = v + + env.AppendENVPath('PATH', get_system_root() + '\System32') + env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD' env['OBJPREFIX'] = '' env['OBJSUFFIX'] = '.obj' diff --git a/src/engine/SCons/Tool/MSCommon/TODO b/src/engine/SCons/Tool/MSCommon/TODO new file mode 100644 index 0000000..be350b8 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/TODO @@ -0,0 +1,5 @@ +Last Change: Fri Oct 17 04:00 PM 2008 J + +- Make sure VS 6 and VS 2003 .Net work (with their own SDK) +- See whether current unit tests can be updated and need to be rewritten from + scratch diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py new file mode 100644 index 0000000..a59bf15 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -0,0 +1,49 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """ +Common functions for Microsoft Visual Studio and Visual C/C++. +""" + +import copy +import os +import re +import subprocess + +import SCons.Errors +import SCons.Platform.win32 +import SCons.Util + +from SCons.Tool.MSCommon.vs import detect_msvs, \ + get_default_version, \ + get_vs_by_version, \ + merge_default_version, \ + query_versions + +# 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/common.py b/src/engine/SCons/Tool/MSCommon/common.py new file mode 100644 index 0000000..619b242 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -0,0 +1,177 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """ +Common helper functions for working with +""" + +import copy +import os +import subprocess +import re + +import SCons.Util + +# Uncomment to enable debug logging to your choice of file +#import logging,os +#os.unlink('c:/tmp/debug.log') +#logging.basicConfig(filename='c:/tmp/debug.log', level=logging.DEBUG,) + +try: + from logging import debug +except ImportError: + debug = lambda x : None + +#debug = lambda x : open('con', 'w').write(x + '\n') + +# TODO(sgk): unused +def is_win64(): + """Return true if running on windows 64 bits.""" + # Unfortunately, python does not seem to have anything useful: neither + # sys.platform nor os.name gives something different on windows running on + # 32 bits or 64 bits. Note that we don't care about whether python itself + # is 32 or 64 bits here + value = "Software\Wow6432Node" + yo = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0] + if yo is None: + return 0 + else: + return 1 + +def read_reg(value): + return SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0] + + +# Functions for fetching environment variable settings from batch files. + +def normalize_env(env, keys): + """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""" + 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): + 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 args: + debug("Calling '%s %s'" % (vcbat, args)) + popen = subprocess.Popen('"%s" %s & set' % (vcbat, args), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + else: + debug("Calling '%s'" % vcbat) + popen = subprocess.Popen('"%s" & set' % vcbat, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + + # 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() + if popen.wait() != 0: + raise IOError(popen.stderr.read().decode("mbcs")) + + output = stdout.decode("mbcs") + return output + +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)) + + # rdk will keep the regex to match the .bat file output line starts + rdk = {} + for i in keep: + rdk[i] = re.compile('%s=(.*)' % i, re.I) + + def add_env(rmatch, key): + plist = rmatch.group(1).split(os.pathsep) + for p in plist: + # Do not add empty paths (when a var ends with ;) + if p: + p = p.encode('mbcs') + # XXX: For some reason, VC98 .bat file adds "" around the PATH + # values, and it screws up the environment later, so we strip + # it. + p = p.strip('"') + dkeep[key].append(p) + + for line in output.splitlines(): + for k,v in rdk.items(): + m = v.match(line) + if m: + add_env(m, k) + + return dkeep + +# TODO(sgk): unused +def output_to_dict(output): + """Given an output string, parse it to find env variables. + + Return a dict where keys are variables names, and values their content""" + envlinem = re.compile(r'^([a-zA-z0-9]+)=([\S\s]*)$') + parsedenv = {} + for line in output.splitlines(): + m = envlinem.match(line) + if m: + parsedenv[m.group(1)] = m.group(2) + return parsedenv + +# TODO(sgk): unused +def get_new(l1, l2): + """Given two list l1 and l2, return the items in l2 which are not in l1. + Order is maintained.""" + + # We don't try to be smart: lists are small, and this is not the bottleneck + # is any case + new = [] + for i in l2: + if i not in l1: + new.append(i) + + return new + +# 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/msvc_changes.txt b/src/engine/SCons/Tool/MSCommon/msvc_changes.txt new file mode 100644 index 0000000..e6acaa8 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/msvc_changes.txt @@ -0,0 +1,90 @@ +The Visual Studio support has been totally revamped. Instead of using registry +magic, we use the .bat files available for each version of visual studio. This +is simpler (does not depend on the version of the compiler), more reliable, and +just plain better. + +Specification +============= + +Tested versions +--------------- + +The following versions have been succesfully tested: + - VS 2008 (express), 32 bits + - VS 2005 (express), 32 bits + - VS 2003 (.Net, pro), 32 bits + +Detection +--------- + +All tools related to the ms toolchain are detected through the same method: + - detect the .bat configuration file (vsvarsall.bat/vsvars32.bat + depending on the version) from the registry + - if registry does not return anything useful, use the VS*COMNTOOLS env + variable. + +A version is detected only when the .bat file actually exists on the +filesystem. Once the .bat file is found, it is executed through a clean +environment, and its output is parsed to get the variables +PATH/LIB/LIBPATH/INCLUDE. Those variables are then added to env['ENV'] + +By default, the most recent detected version is set, and can be queried in +env['MSVS_VERSION'] *after* the tool initialization. The version can be forced +by setting the MSVS_VERSION variable *before* initializing the tool. + +SDK +--- + +Separate SDKs are only supported for the following versions: + - Platform SDK 2003 R1 and R2 + - Windows SDK. I tried the following versions: 6.0, 6.0A (SDK delivered + with VS 2008 express) and 6.1 (Windows SDK 2008). + +Previous SDKs are not available anymore on MS website, so I could not test +them. I believe VS 6 has its own SDK included, as well as VS 2003 .Net. The SDK +is set *after* the msvs tool. + +The version of the SDK can be controlled by the scons variable: + + MSSDK_DIR: If set, specifies the directory location of the + SDK to be used. + + MSSDK_VERSION: If set, specifies the version of the SDK to be used. + +If neither of these is set, MSVS_VERSION is used to pick an appropriate +default. + +Architecture +------------ + +env['MSVS_ARCH'] = 'x86' + 'amd64' + +If not set, the selection logic defaults to x86. Cross compiling has been +disabled, filtering out values not included in version.SUPPORTED_ARCH. +(No tests made with cross compiling.) + +Fundamental changes +=================== + +env["ENV"] has been expanded a bit on windows: + - add %SystemRoot%\system32 in the path for windows + - add COMSPEC (needed by the .bat file execution) + +Internals +========= + +The code can be found in the MSVCCommon submodule: + - findloc: find the product dir from the registry or the shell environment + - versions: query the system for available versions of the VS suite on + the system + - misc: high level functions, *candidates* for the public API. + - sdk: specifics to the SDK detection. + - defaults: default values to use for the paths, to use instead of the + whole env parsing which can be quite slow, but less reliable. Still + experimental, may be removed + - envhelpers: functions to execute a VS .bat file, parse its output, + and get the variables with modified values. + +At this point, no function should be considered public, the exact API is not +good yet. diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py new file mode 100644 index 0000000..8fee916 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -0,0 +1,84 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """ +""" + +import os +import re +import string + +from common import read_reg, debug + +# Original value recorded by dcournapeau +_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot' +# On SGK's system +_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\Microsoft SDKs\.NETFramework\v2.0\InstallationFolder' + +def find_framework_root(): + # XXX: find it from environment (FrameworkDir) + try: + froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) + debug("Found framework install root in registry: %s" % froot) + except WindowsError, e: + debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) + return None + + if not os.path.exists(froot): + debug("%s not found on fs" % froot) + return None + + return froot + +def query_versions(): + froot = find_framework_root() + if froot: + contents = os.listdir(froot) + + l = re.compile('v[0-9]+.*') + versions = filter(lambda e, l=l: l.match(e), contents) + + 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, '.') + # sequence comparison in python is lexicographical + # which is exactly what we want. + # Note we sort backwards so the highest version is first. + return cmp(bbl,aal) + + versions.sort(versrt) + else: + versions = [] + + return versions + +# 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/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py new file mode 100644 index 0000000..80e6852 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -0,0 +1,256 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """Module to detect the Platform/Windows SDK + +PSDK 2003 R1 is the earliest version detected. +""" + +import os + +import SCons.Errors +from SCons.Tool.MSCommon.common import debug, read_reg +import SCons.Util + +# SDK Checks. This is of course a mess as everything else on MS platforms. Here +# is what we do to detect the SDK: +# +# For Windows SDK >= 6.0: just look into the registry entries: +# HKLM\Software\Microsoft\Microsoft SDKs\Windows +# All the keys in there are the available versions. +# +# For Platform SDK before 6.0 (2003 server R1 and R2, etc...), there does not +# seem to be any sane registry key, so the precise location is hardcoded. +# +# For versions below 2003R1, it seems the PSDK is included with Visual Studio? +# +# Also, per the following: +# http://benjamin.smedbergs.us/blog/tag/atl/ +# VC++ Professional comes with the SDK, VC++ Express does not. + +# Location of the SDK (checked for 6.1 only) +_CURINSTALLED_SDK_HKEY_ROOT = \ + r"Software\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder" + + +class SDKDefinition: + """ + An abstract base class for trying to find installed SDK directories. + """ + def __init__(self, version, **kw): + self.version = version + self.__dict__.update(kw) + + def find_install_dir(self): + """Try to find the MS SDK from the registry. + + Return None if failed or the directory does not exist. + """ + if not SCons.Util.can_read_reg: + debug('SCons cannot read registry') + return None + + hkey = self.HKEY_FMT % self.hkey_data + + try: + install_dir = read_reg(hkey) + debug('Found sdk dir in registry: %s' % install_dir) + except WindowsError, e: + debug('Did not find sdk dir key %s in registry' % hkey) + return None + + if not os.path.exists(install_dir): + debug('%s is not found on the filesystem' % install_dir) + return None + + ftc = os.path.join(install_dir, self.sanity_check_file) + if not os.path.exists(ftc): + debug("File %s used for sanity check not found" % ftc) + return None + + return install_dir + + def get_install_dir(self): + """Return the MSSSDK given the version string.""" + try: + return self._install_dir + except AttributeError: + install_dir = self.find_install_dir() + self._install_dir = install_dir + return install_dir + +class WindowsSDK(SDKDefinition): + """ + A subclass for trying to find installed Windows SDK directories. + """ + HKEY_FMT = r'Software\Microsoft\Microsoft SDKs\Windows\v%s\InstallationFolder' + def __init__(self, *args, **kw): + apply(SDKDefinition.__init__, (self,)+args, kw) + self.hkey_data = self.version + +class PlatformSDK(SDKDefinition): + """ + A subclass for trying to find installed Platform SDK directories. + """ + HKEY_FMT = r'Software\Microsoft\MicrosoftSDK\InstalledSDKS\%s\Install Dir' + def __init__(self, *args, **kw): + apply(SDKDefinition.__init__, (self,)+args, kw) + self.hkey_data = self.uuid + +# The list of support SDKs which we know how to detect. +# +# The first SDK found in the list is the one used by default if there +# are multiple SDKs installed. Barring good reasons to the contrary, +# this means we should list SDKs with from most recent to oldest. +# +# If you update this list, update the documentation in Tool/mssdk.xml. +SupportedSDKList = [ + WindowsSDK('6.1', + sanity_check_file=r'include\windows.h'), + + WindowsSDK('6.0A', + sanity_check_file=r'include\windows.h'), + + WindowsSDK('6.0', + sanity_check_file=r'bin\gacutil.exe'), + + PlatformSDK('2003R2', + sanity_check_file=r'SetEnv.Cmd', + uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1"), + + PlatformSDK('2003R1', + sanity_check_file=r'SetEnv.Cmd', + uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3"), +] + +SupportedSDKMap = {} +for sdk in SupportedSDKList: + SupportedSDKMap[sdk.version] = sdk + + +# Finding installed SDKs isn't cheap, because it goes not only to the +# registry but also to the disk to sanity-check that there is, in fact, +# an SDK installed there and that the registry entry isn't just stale. +# Find this information once, when requested, and cache it. + +InstalledSDKList = None +InstalledSDKMap = None + +def get_installed_sdks(): + global InstalledSDKList + global InstalledSDKMap + if InstalledSDKList is None: + InstalledSDKList = [] + InstalledSDKMap = {} + for sdk in SupportedSDKList: + if sdk.get_install_dir(): + InstalledSDKList.append(sdk) + InstalledSDKMap[sdk.version] = sdk + return InstalledSDKList + + +# We may be asked to update multiple construction environments with +# SDK information. When doing this, we check on-disk for whether +# the SDK has 'mfc' and 'atl' subdirectories. Since going to disk +# is expensive, cache results by directory. + +SDKEnvironmentUpdates = {} + +def set_sdk_by_directory(env, sdk_dir): + global SDKEnvironmentUpdates + try: + env_tuple_list = SDKEnvironmentUpdates[sdk_dir] + except KeyError: + env_tuple_list = [] + SDKEnvironmentUpdates[sdk_dir] = env_tuple_list + + include_path = os.path.join(sdk_dir, 'include') + mfc_path = os.path.join(include_path, 'mfc') + atl_path = os.path.join(include_path, 'atl') + + if os.path.exists(mfc_path): + env_tuple_list.append(('INCLUDE', mfc_path)) + if os.path.exists(atl_path): + env_tuple_list.append(('INCLUDE', atl_path)) + env_tuple_list.append(('INCLUDE', include_path)) + + env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib'))) + env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib'))) + env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin'))) + + for variable, directory in env_tuple_list: + env.PrependENVPath(variable, directory) + + +# TODO(sgk): currently unused; remove? +def get_cur_sdk_dir_from_reg(): + """Try to find the platform sdk directory from the registry. + + Return None if failed or the directory does not exist""" + if not SCons.Util.can_read_reg: + debug('SCons cannot read registry') + return None + + try: + val = read_reg(_CURINSTALLED_SDK_HKEY_ROOT) + debug("Found current sdk dir in registry: %s" % val) + except WindowsError, e: + debug("Did not find current sdk in registry") + return None + + if not os.path.exists(val): + debug("Current sdk dir %s not on fs" % val) + return None + + return val + + +def detect_sdk(): + return (len(get_installed_sdks()) > 0) + +def set_sdk_by_version(env, mssdk): + if not SupportedSDKMap.has_key(mssdk): + msg = "SDK version %s is not supported" % repr(mssdk) + raise SCons.Errors.UserError, msg + get_installed_sdks() + sdk = InstalledSDKMap.get(mssdk) + if not sdk: + msg = "SDK version %s is not installed" % repr(mssdk) + raise SCons.Errors.UserError, msg + set_sdk_by_directory(env, sdk.get_install_dir()) + +def set_default_sdk(env, msver): + """Set up the default Platform/Windows SDK.""" + # For MSVS < 8, use integrated windows sdk by default + if msver >= 8: + sdks = get_installed_sdks() + if len(sdks) > 0: + set_sdk_by_directory(env, sdks[0].get_install_dir()) + +# 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 new file mode 100644 index 0000000..a79d039 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -0,0 +1,496 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """Module to detect Visual Studio and/or Visual C/C++ +""" + +import os + +import SCons.Errors +import SCons.Util + +from SCons.Tool.MSCommon.common import debug, \ + read_reg, \ + normalize_env, \ + get_output, \ + parse_output + +class VisualStudio: + """ + An abstract base class for trying to find installed versions of + Visual Studio. + """ + def __init__(self, version, **kw): + self.version = version + self.__dict__.update(kw) + self._cache = {} + + def batch_file_path(self): + pdir = self.get_vc_product_dir() + if not pdir: + return None + return os.path.join(pdir, self.batch_file) + + def common_tools_path(self): + return os.environ.get(self.common_tools_var) + + def vc_product_dir_path(self): + if not SCons.Util.can_read_reg: + debug('SCons can not read registry') + return None + key = self.hkey_root + '\\' + self.vc_product_dir_key + try: + comps = read_reg(key) + except WindowsError, e: + debug('Did not find product dir key %s in registry' % key) + else: + if self.batch_file_dir_reg_relpath: + comps = os.path.join(comps, self.batch_file_dir_reg_relpath) + if os.path.exists(comps): + return comps + debug('%s is not found on the file system' % comps) + + # + + def find_batch_file(self): + """Try to find the Visual Studio or Visual C/C++ batch file. + + Return None if failed or the batch file does not exist. + """ + pdir = self.get_vc_product_dir() + if not pdir: + debug('find_batch_file(); no pdir') + return None + batch_file = os.path.join(pdir, self.batch_file) + if not os.path.isfile(batch_file): + debug('%s file not on file system' % batch_file) + return None + return batch_file + + def find_executable(self): + pdir = self.get_vc_product_dir() + if not pdir: + return None + executable = os.path.join(pdir, self.executable_path) + if not os.path.isfile(executable): + debug('%s file not on file system' % executable) + return None + return executable + + def find_vc_product_dir(self): + if SCons.Util.can_read_reg: + key = self.hkey_root + '\\' + self.vc_product_dir_key + try: + comps = read_reg(key) + except WindowsError, e: + debug('Did not find product dir key %s in registry' % key) + else: + if self.batch_file_dir_reg_relpath: + comps = os.path.join(comps, self.batch_file_dir_reg_relpath) + if os.path.exists(comps): + return comps + debug('%s is not found on the file system' % comps) + else: + debug('SCons can not read registry') + + d = os.environ.get(self.common_tools_var) + if d and os.path.isdir(d): + debug('%s found from %s' % (d, self.common_tools_var)) + if self.batch_file_dir_env_relpath: + d = os.path.join(d, self.batch_file_dir_env_relpath) + return d + return None + + # + + def get_batch_file(self): + try: + return self._cache['batch_file'] + except KeyError: + batch_file = self.find_batch_file() + self._cache['batch_file'] = batch_file + return batch_file + + def get_executable(self): + try: + return self._cache['executable'] + except KeyError: + executable = self.find_executable() + self._cache['executable'] = executable + return executable + + def get_supported_arch(self): + try: + return self._cache['supported_arch'] + except KeyError: + # RDEVE: for the time being use hardcoded lists + # supported_arch = self.find_supported_arch() + self._cache['supported_arch'] = self.supported_arch + return self.supported_arch + + def get_vc_product_dir(self): + try: + return self._cache['vc_product_dir'] + except KeyError: + vc_product_dir = self.find_vc_product_dir() + self._cache['vc_product_dir'] = vc_product_dir + return vc_product_dir + + def reset(self): + self._cache = {} + +# The list of supported Visual Studio versions we know how to detect. +# +# How to look for .bat file ? +# - VS 2008 Express (x86): +# * from registry key productdir, gives the full path to vsvarsall.bat. In +# HKEY_LOCAL_MACHINE): +# Software\Microsoft\VCEpress\9.0\Setup\VC\productdir +# * from environmnent variable VS90COMNTOOLS: the path is then ..\..\VC +# relatively to the path given by the variable. +# +# - VS 2008 Express (WoW6432: 32 bits on windows x64): +# Software\Wow6432Node\Microsoft\VCEpress\9.0\Setup\VC\productdir +# +# - VS 2005 Express (x86): +# * from registry key productdir, gives the full path to vsvarsall.bat. In +# HKEY_LOCAL_MACHINE): +# Software\Microsoft\VCEpress\8.0\Setup\VC\productdir +# * from environmnent variable VS80COMNTOOLS: the path is then ..\..\VC +# relatively to the path given by the variable. +# +# - VS 2005 Express (WoW6432: 32 bits on windows x64): does not seem to have a +# productdir ? +# +# - VS 2003 .Net (pro edition ? x86): +# * from registry key productdir. The path is then ..\Common7\Tools\ +# relatively to the key. The key is in HKEY_LOCAL_MACHINE): +# Software\Microsoft\VisualStudio\7.1\Setup\VC\productdir +# * from environmnent variable VS71COMNTOOLS: the path is the full path to +# vsvars32.bat +# +# - VS 98 (VS 6): +# * from registry key productdir. The path is then Bin +# relatively to the key. The key is in HKEY_LOCAL_MACHINE): +# Software\Microsoft\VisualStudio\6.0\Setup\VC98\productdir +# +# The first version found in the list is the one used by default if +# there are multiple versions installed. Barring good reasons to +# the contrary, this means we should list versions from most recent +# to oldest. Pro versions get listed before Express versions on the +# assumption that, by default, you'd rather use the version you paid +# good money for in preference to whatever Microsoft makes available +# for free. +# +# If you update this list, update the documentation in Tool/msvs.xml. + +SupportedVSList = [ + # Visual Studio 2010 + # TODO: find the settings, perhaps from someone with a CTP copy? + #VisualStudio('TBD', + # hkey_root=r'TBD', + # common_tools_var='TBD', + # batch_file='TBD', + # vc_product_dir_key=r'TBD', + # batch_file_dir_reg_relpath=None, + # batch_file_dir_env_relpath=r'TBD', + # executable_path=r'TBD', + # default_dirname='TBD', + #), + + # Visual Studio 2008 + VisualStudio('9.0', + hkey_root=r'Software\Microsoft\VisualStudio\9.0', + common_tools_var='VS90COMNTOOLS', + batch_file='vcvarsall.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=None, + batch_file_dir_env_relpath=r'..\..\VC', + executable_path=r'..\Common7\IDE\devenv.com', + default_dirname='Microsoft Visual Studio 9', + supported_arch=['x86', 'amd64'], + ), + + # Visual C++ 2008 Express Edition + VisualStudio('9.0Exp', + hkey_root=r'Software\Microsoft\VisualStudio\9.0', + common_tools_var='VS90COMNTOOLS', + batch_file='vcvarsall.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=None, + batch_file_dir_env_relpath=r'..\..\VC', + executable_path=r'..\Common7\IDE\VCExpress.exe', + default_dirname='Microsoft Visual Studio 9', + supported_arch=['x86'], + ), + + # Visual Studio 2005 + VisualStudio('8.0', + hkey_root=r'Software\Microsoft\VisualStudio\8.0', + common_tools_var='VS80COMNTOOLS', + batch_file='vcvarsall.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=None, + batch_file_dir_env_relpath=r'..\..\VC', + executable_path=r'..\Common7\IDE\devenv.com', + default_dirname='Microsoft Visual Studio 8', + supported_arch=['x86', 'amd64'], + ), + + # Visual C++ 2005 Express Edition + VisualStudio('8.0Exp', + hkey_root=r'Software\Microsoft\VCExpress\8.0', + common_tools_var='VS80COMNTOOLS', + batch_file='vcvarsall.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=None, + batch_file_dir_env_relpath=r'..\..\VC', + executable_path=r'..\Common7\IDE\VCExpress.exe', + default_dirname='Microsoft Visual Studio 8', + supported_arch=['x86'], + ), + + # Visual Studio .NET 2003 + VisualStudio('7.1', + hkey_root=r'Software\Microsoft\VisualStudio\7.1', + common_tools_var='VS71COMNTOOLS', + batch_file='vsvars32.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=r'..\Common7\Tools', + batch_file_dir_env_relpath=None, + executable_path=r'..\Common7\IDE\devenv.com', + default_dirname='Microsoft Visual Studio .NET', + supported_arch=['x86'], + ), + + # Visual Studio .NET + VisualStudio('7.0', + hkey_root=r'Software\Microsoft\VisualStudio\7.0', + common_tools_var='VS70COMNTOOLS', + batch_file='vsvars32.bat', + vc_product_dir_key=r'Setup\VC\ProductDir', + batch_file_dir_reg_relpath=r'..\Common7\Tools', + batch_file_dir_env_relpath=None, + executable_path=r'..\Common7\IDE\devenv.com', + default_dirname='Microsoft Visual Studio .NET', + supported_arch=['x86'], + ), + + # Visual Studio 6.0 + VisualStudio('6.0', + hkey_root=r'Software\Microsoft\VisualStudio\6.0', + common_tools_var='VS60COMNTOOLS', + batch_file='vcvars32.bat', + vc_product_dir_key='Setup\Microsoft Visual C++\ProductDir', + batch_file_dir_reg_relpath='Bin', + batch_file_dir_env_relpath=None, + executable_path=r'Common\MSDev98\Bin\MSDEV.COM', + default_dirname='Microsoft Visual Studio', + supported_arch=['x86'], + ), +] + +SupportedVSMap = {} +for vs in SupportedVSList: + SupportedVSMap[vs.version] = vs + + +# Finding installed versions of Visual Studio isn't cheap, because it +# goes not only to the registry but also to the disk to sanity-check +# that there is, in fact, a Visual Studio directory there and that the +# registry entry isn't just stale. Find this information once, when +# requested, and cache it. + +InstalledVSList = None +InstalledVSMap = None + +def get_installed_visual_studios(): + global InstalledVSList + global InstalledVSMap + if InstalledVSList is None: + InstalledVSList = [] + InstalledVSMap = {} + for vs in SupportedVSList: + debug('trying to find %s' % vs.version) + if vs.get_batch_file(): + debug('found %s' % vs.version) + InstalledVSList.append(vs) + InstalledVSMap[vs.version] = vs + return InstalledVSList + +def reset_installed_visual_studios(): + global InstalledVSList + global InstalledVSMap + InstalledVSList = None + InstalledVSMap = None + for vs in SupportedVSList: + vs.reset() + + +# We may be asked to update multiple construction environments with +# SDK information. When doing this, we check on-disk for whether +# the SDK has 'mfc' and 'atl' subdirectories. Since going to disk +# is expensive, cache results by directory. + +#SDKEnvironmentUpdates = {} +# +#def set_sdk_by_directory(env, sdk_dir): +# global SDKEnvironmentUpdates +# try: +# env_tuple_list = SDKEnvironmentUpdates[sdk_dir] +# except KeyError: +# env_tuple_list = [] +# SDKEnvironmentUpdates[sdk_dir] = env_tuple_list +# +# include_path = os.path.join(sdk_dir, 'include') +# mfc_path = os.path.join(include_path, 'mfc') +# atl_path = os.path.join(include_path, 'atl') +# +# if os.path.exists(mfc_path): +# env_tuple_list.append(('INCLUDE', mfc_path)) +# if os.path.exists(atl_path): +# env_tuple_list.append(('INCLUDE', atl_path)) +# env_tuple_list.append(('INCLUDE', include_path)) +# +# env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib'))) +# env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib'))) +# env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin'))) +# +# for variable, directory in env_tuple_list: +# env.PrependENVPath(variable, directory) + +def detect_msvs(): + return (len(get_installed_visual_studios()) > 0) + +def get_vs_by_version(msvs): + if not SupportedVSMap.has_key(msvs): + msg = "Visual Studio version %s is not supported" % repr(msvs) + raise SCons.Errors.UserError, msg + get_installed_visual_studios() + vs = InstalledVSMap.get(msvs) + # Some check like this would let us provide a useful error message + # if they try to set a Visual Studio version that's not installed. + # However, we also want to be able to run tests (like the unit + # tests) on systems that don't, or won't ever, have it installed. + # It might be worth resurrecting this, with some configurable + # setting that the tests can use to bypass the check. + #if not vs: + # msg = "Visual Studio version %s is not installed" % repr(msvs) + # raise SCons.Errors.UserError, msg + return vs + +def get_default_version(env): + """Returns the default version string to use for MSVS. + + If no version was requested by the user through the MSVS environment + variable, query all the available the visual studios through + query_versions, and take the highest one. + + Return + ------ + 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()) + env['MSVS'] = {'VERSIONS' : versions} + else: + versions = env['MSVS'].get('VERSIONS', []) + + if not env.has_key('MSVS_VERSION'): + if versions: + env['MSVS_VERSION'] = versions[0] #use highest version by default + else: + env['MSVS_VERSION'] = SupportedVSList[0].version + + env['MSVS']['VERSION'] = env['MSVS_VERSION'] + + return env['MSVS_VERSION'] + +def get_default_arch(env): + """Return the default arch to use for MSVS + + if no version was requested by the user through the MSVS_ARCH environment + variable, select x86 + + Return + ------ + arch: str + """ + arch = env.get('MSVS_ARCH', 'x86') + + msvs = InstalledVSMap.get(env['MSVS_VERSION']) + + if not msvs: + 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) + + return arch + +def merge_default_version(env): + version = get_default_version(env) + arch = get_default_arch(env) + + msvs = get_vs_by_version(version) + if msvs is None: + return + batfilename = msvs.get_batch_file() + + # XXX: I think this is broken. This will silently set a bogus tool instead + # of failing, but there is no other way with the current scons tool + # framework + if batfilename is not None: + + 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) + vars = parse_output(output, vars) + + for k, v in vars.items(): + env.PrependENVPath(k, v, delete_existing=1) + +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) + return versions + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py index 43eb953..3aeb693 100644 --- a/src/engine/SCons/Tool/linkloc.py +++ b/src/engine/SCons/Tool/linkloc.py @@ -43,7 +43,7 @@ import SCons.Errors import SCons.Tool import SCons.Util -from SCons.Tool.msvc import get_msvc_paths +from SCons.Tool.MSCommon import detect_msvs, merge_default_version from SCons.Tool.PharLapCommon import addPharLapPaths _re_linker_command = re.compile(r'(\s)@\s*([^\s]+)') @@ -94,15 +94,16 @@ def generate(env): env['LIBLINKPREFIX']='-lib ' env['LIBLINKSUFFIX']='$LIBSUFFIX' - msvs_version = env.get('MSVS_VERSION') - include_path, lib_path, exe_path = get_msvc_paths(env, version = msvs_version) - env['ENV']['LIB'] = lib_path - env.PrependENVPath('PATH', exe_path) + # Set-up ms tools paths for default version + merge_default_version(env) addPharLapPaths(env) def exists(env): - return env.Detect('linkloc') + if detect_msvs(): + return env.Detect('linkloc') + else: + return 0 # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py index 8347bc1..441f884 100644 --- a/src/engine/SCons/Tool/midl.py +++ b/src/engine/SCons/Tool/midl.py @@ -41,6 +41,8 @@ import SCons.Defaults import SCons.Scanner.IDL import SCons.Util +from MSCommon import detect_msvs + def midl_emitter(target, source, env): """Produces a list of outputs from the MIDL compiler""" base, ext = SCons.Util.splitext(str(target[0])) @@ -79,15 +81,7 @@ def generate(env): env['BUILDERS']['TypeLibrary'] = midl_builder def exists(env): - if not env['PLATFORM'] in ('win32', 'cygwin'): - return 0 - - import SCons.Tool.msvs - if SCons.Tool.msvs.is_msvs_installed(): - # there's at least one version of MSVS installed, which comes with midl: - return 1 - else: - return env.Detect('midl') + return detect_msvs() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index dcb57fa..d23f63b 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -39,23 +39,14 @@ import SCons.Tool.msvs import SCons.Tool.msvc import SCons.Util +from MSCommon import detect_msvs, merge_default_version + def generate(env): """Add Builders and construction variables for lib to an Environment.""" SCons.Tool.createStaticLibBuilder(env) - try: - 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 = SCons.Tool.msvc.get_msvc_default_paths(env,version) - else: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version) - - # since other tools can set this, we just make sure that the - # relevant stuff from MSVS is in there somewhere. - env.PrependENVPath('PATH', exe_path) - except (SCons.Util.RegError, SCons.Errors.InternalError): - pass + # Set-up ms tools paths for default version + merge_default_version(env) env['AR'] = 'lib' env['ARFLAGS'] = SCons.Util.CLVar('/nologo') @@ -64,16 +55,7 @@ def generate(env): env['LIBSUFFIX'] = '.lib' def exists(env): - try: - v = SCons.Tool.msvs.get_visualstudio_versions() - except (SCons.Util.RegError, SCons.Errors.InternalError): - pass - - if not v: - return env.Detect('lib') - else: - # there's at least one version of MSVS installed. - return 1 + return detect_msvs() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 2a2ec05..d2089d3 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -44,6 +44,8 @@ import SCons.Tool.msvc import SCons.Tool.msvs import SCons.Util +from MSCommon import merge_default_version, detect_msvs + def pdbGenerator(env, target, source, for_signature): try: return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG'] @@ -236,21 +238,8 @@ def generate(env): env['REGSVRFLAGS'] = '/s ' env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}' - try: - 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 = SCons.Tool.msvc.get_msvc_default_paths(env,version) - else: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,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) - except (SCons.Util.RegError, SCons.Errors.InternalError): - pass + # Set-up ms tools paths for default version + merge_default_version(env) # Loadable modules are on Windows the same as shared libraries, but they # are subject to different build parameters (LDMODULE* variables). @@ -267,17 +256,7 @@ def generate(env): env['LDMODULECOM'] = compositeLdmodAction def exists(env): - platform = env.get('PLATFORM', '') - if SCons.Tool.msvs.is_msvs_installed(): - # there's at least one version of MSVS installed. - return 1 - elif platform in ('win32', 'cygwin'): - # Only explicitly search for a 'link' executable on Windows - # systems. Some other systems (e.g. Ubuntu Linux) have an - # executable named 'link' and we don't want that to make SCons - # think Visual Studio is installed. - return env.Detect('link') - return None + return detect_msvs() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mssdk.py b/src/engine/SCons/Tool/mssdk.py new file mode 100644 index 0000000..652a0c2 --- /dev/null +++ b/src/engine/SCons/Tool/mssdk.py @@ -0,0 +1,64 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +"""engine.SCons.Tool.mssdk + +Tool-specific initialization for Microsoft SDKs, both Platform +SDKs and Windows SDKs. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. +""" + +from SCons.Tool.MSCommon.sdk import detect_sdk, \ + set_default_sdk, \ + set_sdk_by_directory, \ + set_sdk_by_version + +def generate(env): + """Add construction variables for an MS SDK to an Environment.""" + if env.has_key('MSSDK_DIR'): + set_sdk_by_directory(env, env.subst('$MSSDK_DIR')) + return + + if env.has_key('MSSDK_VERSION'): + set_sdk_by_version(env, env.subst('$MSSDK_VERSION')) + return + + if env.has_key('MSVS_VERSION'): + set_default_sdk(env, env['MSVS_VERSION']) + + #print "No MSVS_VERSION: this is likely to be a bug" + return + +def exists(env): + return detect_sdk() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/mssdk.xml b/src/engine/SCons/Tool/mssdk.xml new file mode 100644 index 0000000..bdfd394 --- /dev/null +++ b/src/engine/SCons/Tool/mssdk.xml @@ -0,0 +1,50 @@ +<!-- +__COPYRIGHT__ + +This file is processed by the bin/SConsDoc.py module. +See its __doc__ string for a discussion of the format. +--> +<tool name="mssdk"> +<summary> +Sets variables for Microsoft Platform SDK and/or Windows SDK. +Note that unlike most other Tool modules, +mssdk does not set construction variables, +but sets the <emphasis>environment variables</emphasis> +in the environment &SCons; uses to execute +the Microsoft toolchain: +<literal>%INCLUDE%</literal>, +<literal>%LIB%</literal>, +<literal>%LIBPATH%</literal> and +<literal>%PATH%</literal>. +</summary> +<sets> +</sets> +<uses> +MSSDK_DIR +MSSDK_VERSION +MSVS_VERSION +</uses> +</tool> + +<cvar name="MSSDK_DIR"> +<summary> +The directory containing the Microsoft SDK +(either Platform SDK or Windows SDK) +to be used for compilation. +</summary> +</cvar> + +<cvar name="MSSDK_VERSION"> +<summary> +The version string of the Microsoft SDK +(either Platform SDK or Windows SDK) +to be used for compilation. +Supported versions include +<literal>6.1</literal>, +<literal>6.0A</literal>, +<literal>6.0</literal>, +<literal>2003R2</literal> +and +<literal>2003R1</literal>. +</summary> +</cvar> diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 443e8b0..e68f982 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -36,6 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os.path import re import string +import sys import SCons.Action import SCons.Builder @@ -47,567 +48,11 @@ import SCons.Util import SCons.Warnings import SCons.Scanner.RC +from MSCommon import merge_default_version, detect_msvs + CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] -def _parse_msvc7_overrides(version,platform): - """ 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" - - 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 + '\\VCComponents.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... - lines = None - try: - import codecs - except ImportError: - pass - else: - try: - f = codecs.open(comps, 'r', 'utf16') - encoder = codecs.getencoder('ascii') - lines = map(lambda l, e=encoder: e(l)[0], f.readlines()) - except (LookupError, UnicodeError): - lines = codecs.open(comps, 'r', 'utf8').readlines() - if lines is None: - lines = open(comps, 'r').readlines() - if 'x86' == platform: platform = 'Win32' - - found = 0 - for line in lines: - line.strip() - if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories]'%platform) >= 0: - found = 1 - elif line == '' or line[:1] == '[': - found = 0 - elif found == 1: - kv = line.split('=', 1) - if len(kv) == 2: - (key, val) = kv - key = key.replace(' Dirs','') - dirs[key.upper()] = val - f.close() - else: - # since the file didn't exist, we have only the defaults in - # the registry to work with. - - if 'x86' == platform: platform = 'Win32' - - try: - K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version - K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories'%platform - k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K) - i = 0 - while 1: - try: - (key,val,t) = SCons.Util.RegEnumValue(k,i) - key = key.replace(' Dirs','') - dirs[key.upper()] = val - i = i + 1 - except SCons.Util.RegError: - break - except SCons.Util.RegError: - # 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 _parse_msvc8_overrides(version,platform,suite): - """ Parse any overridden defaults for MSVC directory locations - in MSVC 2005. """ - - # In VS8 the user can change the location of the settings file that - # contains the include, lib and binary paths. Try to get the location - # from registry - if not SCons.Util.can_read_reg: - raise SCons.Errors.InternalError, "No Windows registry module was found" - - # XXX This code assumes anything that isn't EXPRESS uses the default - # registry key string. Is this really true for all VS suites? - if suite == 'EXPRESS': - s = '\\VCExpress\\' - else: - s = '\\VisualStudio\\' - - settings_path = "" - try: - (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER, - r'Software\Microsoft' + s + version +\ - r'\Profile\AutoSaveFile') - settings_path = settings_path.upper() - except SCons.Util.RegError: - raise SCons.Errors.InternalError, \ - "The VS8 settings file location was not found in the registry." - - # Look for potential environment variables in the settings path - if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0: - # First replace a special variable named %vsspv_visualstudio_dir% - # that is not found in the OSs environment variables... - try: - (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER, - r'Software\Microsoft' + s + version +\ - r'\VisualStudioLocation') - settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value) - except SCons.Util.RegError: - raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry." - - if settings_path.find('%') >= 0: - # Collect global environment variables - env_vars = {} - - # Read all the global environment variables of the current user - k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment') - i = 0 - while 1: - try: - (key,val,t) = SCons.Util.RegEnumValue(k,i) - env_vars[key.upper()] = val.upper() - i = i + 1 - except SCons.Util.RegError: - break - - # And some more variables that are not found in the registry - env_vars['USERPROFILE'] = os.getenv('USERPROFILE') - env_vars['SystemDrive'] = os.getenv('SystemDrive') - - found_var = 1 - while found_var: - found_var = 0 - for env_var in env_vars: - if settings_path.find(r'%' + env_var + r'%') >= 0: - settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var]) - found_var = 1 - - dirs = {} - - if os.path.exists(settings_path): - # now we parse the directories from this file, if it exists. - import xml.dom.minidom - doc = xml.dom.minidom.parse(settings_path) - user_settings = doc.getElementsByTagName('UserSettings')[0] - tool_options = user_settings.getElementsByTagName('ToolsOptions')[0] - tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory') - environment_var_map = { - 'IncludeDirectories' : 'INCLUDE', - 'LibraryDirectories' : 'LIBRARY', - 'ExecutableDirectories' : 'PATH', - } - for category in tool_options_categories: - category_name = category.attributes.get('name') - if category_name is not None and category_name.value == 'Projects': - subcategories = category.getElementsByTagName('ToolsOptionsSubCategory') - for subcategory in subcategories: - subcategory_name = subcategory.attributes.get('name') - if subcategory_name is not None and subcategory_name.value == 'VCDirectories': - properties = subcategory.getElementsByTagName('PropertyValue') - for property in properties: - property_name = property.attributes.get('name') - if property_name is None: - continue - var_name = environment_var_map.get(property_name) - if var_name: - data = property.childNodes[0].data - value_list = string.split(data, '|') - if len(value_list) == 1: - dirs[var_name] = value_list[0] - else: - while value_list: - dest, value = value_list[:2] - del value_list[:2] - # ToDo: Support for destinations - # other than Win32 - if dest == 'Win32': - dirs[var_name] = value - break - else: - # There are no default directories in the registry for VS8 Express :( - 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,platform) - - 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, paths=paths): - key = string.upper(match.group(1)) - if paths.has_key(key): - return paths[key] - else: - # Now look in the global environment variables - envresult = os.getenv(key) - if not envresult is None: - return envresult + '\\' - else: - return '---Unknown Location %s---' % match.group() - - rv = [] - for entry in p.split(os.pathsep): - entry = s.sub(repl,entry).rstrip('\n\r') - rv.append(entry) - - return string.join(rv,os.pathsep) - -def _get_msvc8_path(path, version, platform, suite): - """ - Get Visual Studio directories from version 8 (MSVS 2005) - (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_msvc8_overrides(version, platform, suite) - - 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, suite) - - # 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, paths=paths): - key = string.upper(match.group(1)) - if paths.has_key(key): - return paths[key] - else: - return '---Unknown Location %s---' % match.group() - - rv = [] - for entry in p.split(os.pathsep): - entry = s.sub(repl,entry).rstrip('\n\r') - rv.append(entry) - - return string.join(rv,os.pathsep) - -def get_msvc_path(env, path, version): - """ - Get a list of visualstudio directories (include, lib or path). - Return a string delimited by the os.pathsep separator (';'). An - exception will be raised if unable to access the registry or - appropriate registry keys not found. - """ - - if not SCons.Util.can_read_reg: - raise SCons.Errors.InternalError, "No Windows registry module was found" - - # normalize the case for comparisons (since the registry is case - # insensitive) - path = string.upper(path) - - if path=='LIB': - path= 'LIBRARY' - - version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) - if version_num >= 8.0: - platform = env.get('MSVS8_PLATFORM', 'x86') - suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) - else: - platform = 'x86' - - if version_num >= 8.0: - return _get_msvc8_path(path, str(version_num), platform, suite) - elif version_num >= 7.0: - return _get_msvc7_path(path, str(version_num), platform) - - path = string.upper(path + ' Dirs') - K = ('Software\\Microsoft\\Devstudio\\%s\\' + - 'Build System\\Components\\Platforms\\Win32 (x86)\\Directories') % \ - (version) - for base in (SCons.Util.HKEY_CURRENT_USER, - SCons.Util.HKEY_LOCAL_MACHINE): - try: - k = SCons.Util.RegOpenKeyEx(base,K) - i = 0 - while 1: - try: - (p,v,t) = SCons.Util.RegEnumValue(k,i) - if string.upper(p) == path: - return v - i = i + 1 - except SCons.Util.RegError: - break - except SCons.Util.RegError: - pass - - # if we got here, then we didn't find the registry entries: - raise SCons.Errors.InternalError, "The %s path was not found in the registry."%path - -def _get_msvc6_default_paths(version, use_mfc_dirs): - """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, KeyError): - 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 - if use_mfc_dirs: - mfc_include_ = r'%s\ATL\include;%s\MFC\include;' % (MVSVCdir, MVSVCdir) - mfc_lib_ = r'%s\MFC\lib;' % MVSVCdir - else: - mfc_include_ = '' - mfc_lib_ = '' - include_path = r'%s%s\include' % (mfc_include_, MVSVCdir) - lib_path = r'%s%s\lib' % (mfc_lib_, MVSVCdir) - - if os.environ.has_key('OS') and os.environ['OS'] == "Windows_NT": - osdir = 'WINNT' - else: - osdir = 'WIN95' - - exe_path = r'%s\tools\%s;%s\MSDev98\bin;%s\tools;%s\bin' % (MVSCommondir, osdir, MVSCommondir, MVSCommondir, MVSVCdir) - return (include_path, lib_path, exe_path) - -def _get_msvc7_default_paths(env, version, use_mfc_dirs): - """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 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 - if use_mfc_dirs: - mfc_include_ = r'%s\atlmfc\include;' % MVSVCdir - mfc_lib_ = r'%s\atlmfc\lib;' % MVSVCdir - else: - mfc_include_ = '' - mfc_lib_ = '' - include_path = r'%s%s\include;%s\PlatformSDK\include' % (mfc_include_, MVSVCdir, MVSVCdir) - lib_path = r'%s%s\lib;%s\PlatformSDK\lib' % (mfc_lib_, MVSVCdir, MVSVCdir) - exe_path = r'%s\IDE;%s\bin;%s\Tools;%s\Tools\bin' % (MVSCommondir,MVSVCdir, MVSCommondir, MVSCommondir ) - - if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'): - include_path = include_path + r';%s\include'%paths['FRAMEWORKSDKDIR'] - lib_path = lib_path + r';%s\lib'%paths['FRAMEWORKSDKDIR'] - exe_path = exe_path + r';%s\bin'%paths['FRAMEWORKSDKDIR'] - - if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'): - exe_path = exe_path + r';%s\%s'%(paths['FRAMEWORKDIR'],paths['FRAMEWORKVERSION']) - - return (include_path, lib_path, exe_path) - -def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs): - """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 8 tools properly, if the information wasn't available - from the registry.""" - - MVSdir = None - paths = {} - exe_paths = [] - lib_paths = [] - include_paths = [] - try: - paths = SCons.Tool.msvs.get_msvs_install_dirs(version, suite) - 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 = os.getenv('ProgramFiles') + r'\Microsoft Visual Studio 8' - - if MVSdir: - if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'): - MVSVCdir = paths['VCINSTALLDIR'] - else: - MVSVCdir = os.path.join(MVSdir,'VC') - - MVSCommondir = os.path.join(MVSdir, 'Common7') - include_paths.append( os.path.join(MVSVCdir, 'include') ) - lib_paths.append( os.path.join(MVSVCdir, 'lib') ) - for base, subdir in [(MVSCommondir,'IDE'), (MVSVCdir,'bin'), - (MVSCommondir,'Tools'), (MVSCommondir,r'Tools\bin')]: - exe_paths.append( os.path.join( base, subdir) ) - - if paths.has_key('PLATFORMSDKDIR'): - PlatformSdkDir = paths['PLATFORMSDKDIR'] - else: - PlatformSdkDir = os.path.join(MVSVCdir,'PlatformSDK') - platform_include_path = os.path.join( PlatformSdkDir, 'Include' ) - include_paths.append( platform_include_path ) - lib_paths.append( os.path.join( PlatformSdkDir, 'Lib' ) ) - if use_mfc_dirs: - if paths.has_key('PLATFORMSDKDIR'): - include_paths.append( os.path.join( platform_include_path, 'mfc' ) ) - include_paths.append( os.path.join( platform_include_path, 'atl' ) ) - else: - atlmfc_path = os.path.join( MVSVCdir, 'atlmfc' ) - include_paths.append( os.path.join( atlmfc_path, 'include' ) ) - lib_paths.append( os.path.join( atlmfc_path, 'lib' ) ) - - if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'): - fwdir = paths['FRAMEWORKSDKDIR'] - include_paths.append( os.path.join( fwdir, 'include' ) ) - lib_paths.append( os.path.join( fwdir, 'lib' ) ) - exe_paths.append( os.path.join( fwdir, 'bin' ) ) - - if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'): - exe_paths.append( os.path.join( paths['FRAMEWORKDIR'], paths['FRAMEWORKVERSION'] ) ) - - include_path = string.join( include_paths, os.pathsep ) - lib_path = string.join(lib_paths, os.pathsep ) - exe_path = string.join(exe_paths, os.pathsep ) - return (include_path, lib_path, exe_path) - -def get_msvc_paths(env, version=None, use_mfc_dirs=0): - """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: - versions = SCons.Tool.msvs.get_visualstudio_versions() - if versions: - version = versions[0] #use highest version by default - else: - version = '6.0' - - # 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. - version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) - if version_num >= 8.0: - suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) - defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs) - elif version_num >= 7.0: - defpaths = _get_msvc7_default_paths(env, version, use_mfc_dirs) - else: - defpaths = _get_msvc6_default_paths(version, use_mfc_dirs) - - try: - include_path = get_msvc_path(env, "include", version) - except (SCons.Util.RegError, SCons.Errors.InternalError): - include_path = defpaths[0] - - try: - lib_path = get_msvc_path(env, "lib", version) - except (SCons.Util.RegError, SCons.Errors.InternalError): - lib_path = defpaths[1] - - try: - exe_path = get_msvc_path(env, "path", version) - except (SCons.Util.RegError, SCons.Errors.InternalError): - exe_path = defpaths[2] - - return (include_path, lib_path, exe_path) - -def get_msvc_default_paths(env, version=None, use_mfc_dirs=0): - """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 = SCons.Tool.msvs.get_visualstudio_versions()[0] #use highest version - except KeyboardInterrupt: - raise - except: - pass - - version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) - if version_num >= 8.0: - suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) - return _get_msvc8_default_paths(env, version, suite, use_mfc_dirs) - elif version_num >= 7.0: - return _get_msvc7_default_paths(env, version, use_mfc_dirs) - else: - return _get_msvc6_default_paths(version, use_mfc_dirs) - def validate_vars(env): """Validate the PCH and PCHSTOP construction variables.""" if env.has_key('PCH') and env['PCH']: @@ -787,26 +232,11 @@ def generate(env): env['SHOBJPREFIX'] = '$OBJPREFIX' env['SHOBJSUFFIX'] = '$OBJSUFFIX' - try: - version = SCons.Tool.msvs.get_default_visualstudio_version(env) - version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) - if version_num == 8.0: - suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) - - use_mfc_dirs = env.get('MSVS_USE_MFC_DIRS', 0) - if env.get('MSVS_IGNORE_IDE_PATHS', 0): - _get_paths = get_msvc_default_paths - else: - _get_paths = get_msvc_paths - include_path, lib_path, exe_path = _get_paths(env, version, use_mfc_dirs) - - # 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) - except (SCons.Util.RegError, SCons.Errors.InternalError): - pass + # Set-up ms tools paths for default version + merge_default_version(env) + + import mssdk + mssdk.generate(env) env['CFILESUFFIX'] = '.c' env['CXXFILESUFFIX'] = '.cc' @@ -821,11 +251,7 @@ def generate(env): env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root() def exists(env): - if SCons.Tool.msvs.is_msvs_installed(): - # there's at least one version of MSVS installed. - return 1 - else: - return env.Detect('cl') + return detect_msvs() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index f80564b..4d40d8c 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -49,6 +49,8 @@ import SCons.Script.SConscript import SCons.Util import SCons.Warnings +from MSCommon import detect_msvs, merge_default_version + ############################################################################## # Below here are the classes and functions for generation of # DSP/DSW/SLN/VCPROJ files. @@ -1155,375 +1157,6 @@ def GenerateDSW(dswfile, source, env): # DSP/DSW/SLN/VCPROJ files. ############################################################################## -def get_default_visualstudio_version(env): - """Returns the version set in the env, or the latest version - installed, if it can find it, or '6.0' if all else fails. Also - updates the environment with what it found.""" - - versions = ['6.0'] - - if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']): - v = get_visualstudio_versions() - if v: - versions = v - env['MSVS'] = {'VERSIONS' : versions} - else: - versions = env['MSVS'].get('VERSIONS', versions) - - if not env.has_key('MSVS_VERSION'): - env['MSVS_VERSION'] = versions[0] #use highest version by default - - env['MSVS']['VERSION'] = env['MSVS_VERSION'] - - return env['MSVS_VERSION'] - -def get_visualstudio_versions(): - """ - Get list of visualstudio versions from the Windows registry. - Returns a list of strings containing version numbers. An empty list - is returned if we were unable to accees the register (for example, - we couldn't import the registry-access module) or the appropriate - registry keys weren't found. - """ - - if not SCons.Util.can_read_reg: - return [] - - HLM = SCons.Util.HKEY_LOCAL_MACHINE - KEYS = { - r'Software\Microsoft\VisualStudio' : '', - r'Software\Microsoft\VCExpress' : 'Exp', - } - L = [] - for K, suite_suffix in KEYS.items(): - try: - k = SCons.Util.RegOpenKeyEx(HLM, K) - i = 0 - while 1: - try: - p = SCons.Util.RegEnumKey(k,i) - except SCons.Util.RegError: - break - i = i + 1 - if not p[0] in '123456789' or p in L: - continue - # Only add this version number if there is a valid - # registry structure (includes the "Setup" key), - # and at least some of the correct directories - # exist. Sometimes VS uninstall leaves around - # some registry/filesystem turds that we don't - # want to trip over. Also, some valid registry - # entries are MSDN entries, not MSVS ('7.1', - # notably), and we want to skip those too. - try: - SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p + '\\Setup') - except SCons.Util.RegError: - continue - - id = [] - idk = SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p) - # This is not always here -- it only exists if the - # user installed into a non-standard location (at - # least in VS6 it works that way -- VS7 seems to - # always write it) - try: - id = SCons.Util.RegQueryValueEx(idk, 'InstallDir') - except SCons.Util.RegError: - pass - - # If the InstallDir key doesn't exist, - # then we check the default locations. - # Note: The IDE's executable is not devenv.exe for VS8 Express. - if not id or not id[0]: - files_dir = SCons.Platform.win32.get_program_files_dir() - version_num, suite = msvs_parse_version(p) - if version_num < 7.0: - vs = r'Microsoft Visual Studio\Common\MSDev98' - elif version_num < 8.0: - vs = r'Microsoft Visual Studio .NET\Common7\IDE' - else: - vs = r'Microsoft Visual Studio 8\Common7\IDE' - id = [ os.path.join(files_dir, vs) ] - if os.path.exists(id[0]): - L.append(p + suite_suffix) - except SCons.Util.RegError: - pass - - if not L: - return [] - - # This is a hack to get around the fact that certain Visual Studio - # patches place a "6.1" version in the registry, which does not have - # any of the keys we need to find include paths, install directories, - # etc. Therefore we ignore it if it is there, since it throws all - # other logic off. - try: - L.remove("6.1") - except ValueError: - pass - - L.sort() - L.reverse() - - return L - -def get_default_visualstudio8_suite(env): - """ - Returns the Visual Studio 2005 suite identifier set in the env, or the - highest suite installed. - """ - if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']): - env['MSVS'] = {} - - if env.has_key('MSVS_SUITE'): - # TODO(1.5) - #suite = env['MSVS_SUITE'].upper() - suite = string.upper(env['MSVS_SUITE']) - suites = [suite] - else: - suite = 'EXPRESS' - suites = [suite] - if SCons.Util.can_read_reg: - suites = get_visualstudio8_suites() - if suites: - suite = suites[0] #use best suite by default - - env['MSVS_SUITE'] = suite - env['MSVS']['SUITES'] = suites - env['MSVS']['SUITE'] = suite - - return suite - -def get_visualstudio8_suites(): - """ - Returns a sorted list of all installed Visual Studio 2005 suites found - in the registry. The highest version should be the first entry in the list. - """ - - suites = [] - - # Detect Standard, Professional and Team edition - try: - idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, - r'Software\Microsoft\VisualStudio\8.0') - SCons.Util.RegQueryValueEx(idk, 'InstallDir') - editions = { 'PRO': r'Setup\VS\Pro' } # ToDo: add standard and team editions - edition_name = 'STD' - for name, key_suffix in editions.items(): - try: - idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, - r'Software\Microsoft\VisualStudio\8.0' + '\\' + key_suffix ) - edition_name = name - except SCons.Util.RegError: - pass - suites.append(edition_name) - except SCons.Util.RegError: - pass - - # Detect Express edition - try: - idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, - r'Software\Microsoft\VCExpress\8.0') - SCons.Util.RegQueryValueEx(idk, 'InstallDir') - suites.append('EXPRESS') - except SCons.Util.RegError: - pass - - return suites - -def is_msvs_installed(): - """ - Check the registry for an installed visual studio. - """ - try: - v = SCons.Tool.msvs.get_visualstudio_versions() - return v - except (SCons.Util.RegError, SCons.Errors.InternalError): - return 0 - -def get_msvs_install_dirs(version = None, vs8suite = None): - """ - Get installed locations for various msvc-related products, like the .NET SDK - and the Platform SDK. - """ - - if not SCons.Util.can_read_reg: - return {} - - if not version: - versions = get_visualstudio_versions() - if versions: - version = versions[0] #use highest version by default - else: - return {} - - version_num, suite = msvs_parse_version(version) - - K = 'Software\\Microsoft\\VisualStudio\\' + str(version_num) - if (version_num >= 8.0): - if vs8suite == None: - # We've been given no guidance about which Visual Studio 8 - # suite to use, so attempt to autodetect. - suites = get_visualstudio8_suites() - if suites: - vs8suite = suites[0] - - if vs8suite == 'EXPRESS': - K = 'Software\\Microsoft\\VCExpress\\' + str(version_num) - - # vc++ install dir - rv = {} - if (version_num < 7.0): - key = K + r'\Setup\Microsoft Visual C++\ProductDir' - else: - key = K + r'\Setup\VC\ProductDir' - try: - (rv['VCINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, key) - except SCons.Util.RegError: - pass - - # visual studio install dir - if (version_num < 7.0): - try: - (rv['VSINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - K + r'\Setup\Microsoft Visual Studio\ProductDir') - except SCons.Util.RegError: - pass - - if not rv.has_key('VSINSTALLDIR') or not rv['VSINSTALLDIR']: - if rv.has_key('VCINSTALLDIR') and rv['VCINSTALLDIR']: - rv['VSINSTALLDIR'] = os.path.dirname(rv['VCINSTALLDIR']) - else: - rv['VSINSTALLDIR'] = os.path.join(SCons.Platform.win32.get_program_files_dir(),'Microsoft Visual Studio') - else: - try: - (rv['VSINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - K + r'\Setup\VS\ProductDir') - except SCons.Util.RegError: - pass - - # .NET framework install dir - try: - (rv['FRAMEWORKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - r'Software\Microsoft\.NETFramework\InstallRoot') - except SCons.Util.RegError: - pass - - if rv.has_key('FRAMEWORKDIR'): - # try and enumerate the installed versions of the .NET framework. - contents = os.listdir(rv['FRAMEWORKDIR']) - l = re.compile('v[0-9]+.*') - installed_framework_versions = filter(lambda e, l=l: l.match(e), contents) - - 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, '.') - # sequence comparison in python is lexicographical - # which is exactly what we want. - # Note we sort backwards so the highest version is first. - return cmp(bbl,aal) - - installed_framework_versions.sort(versrt) - - rv['FRAMEWORKVERSIONS'] = installed_framework_versions - - # TODO: allow a specific framework version to be set - - # Choose a default framework version based on the Visual - # Studio version. - DefaultFrameworkVersionMap = { - '7.0' : 'v1.0', - '7.1' : 'v1.1', - '8.0' : 'v2.0', - # TODO: Does .NET 3.0 need to be worked into here somewhere? - } - try: - default_framework_version = DefaultFrameworkVersionMap[version[:3]] - except (KeyError, TypeError): - pass - else: - # Look for the first installed directory in FRAMEWORKDIR that - # begins with the framework version string that's appropriate - # for the Visual Studio version we're using. - for v in installed_framework_versions: - if v[:4] == default_framework_version: - rv['FRAMEWORKVERSION'] = v - break - - # If the framework version couldn't be worked out by the previous - # code then fall back to using the latest version of the .NET - # framework - if not rv.has_key('FRAMEWORKVERSION'): - rv['FRAMEWORKVERSION'] = installed_framework_versions[0] - - # .NET framework SDK install dir - if rv.has_key('FRAMEWORKVERSION'): - # The .NET SDK version used must match the .NET version used, - # so we deliberately don't fall back to other .NET framework SDK - # versions that might be present. - ver = rv['FRAMEWORKVERSION'][:4] - key = r'Software\Microsoft\.NETFramework\sdkInstallRoot' + ver - try: - (rv['FRAMEWORKSDKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - key) - except SCons.Util.RegError: - pass - - # MS Platform SDK dir - try: - (rv['PLATFORMSDKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - r'Software\Microsoft\MicrosoftSDK\Directories\Install Dir') - except SCons.Util.RegError: - pass - - if rv.has_key('PLATFORMSDKDIR'): - # if we have a platform SDK, try and get some info on it. - vers = {} - try: - loc = r'Software\Microsoft\MicrosoftSDK\InstalledSDKs' - k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,loc) - i = 0 - while 1: - try: - key = SCons.Util.RegEnumKey(k,i) - sdk = SCons.Util.RegOpenKeyEx(k,key) - j = 0 - name = '' - date = '' - version = '' - while 1: - try: - (vk,vv,t) = SCons.Util.RegEnumValue(sdk,j) - # TODO(1.5): - #if vk.lower() == 'keyword': - # name = vv - #if vk.lower() == 'propagation_date': - # date = vv - #if vk.lower() == 'version': - # version = vv - if string.lower(vk) == 'keyword': - name = vv - if string.lower(vk) == 'propagation_date': - date = vv - if string.lower(vk) == 'version': - version = vv - j = j + 1 - except SCons.Util.RegError: - break - if name: - vers[name] = (date, version) - i = i + 1 - except SCons.Util.RegError: - break - rv['PLATFORMSDK_MODULES'] = vers - except SCons.Util.RegError: - pass - - return rv - def GetMSVSProjectSuffix(target, source, env, for_signature): return env['MSVS']['PROJECTSUFFIX'] @@ -1767,17 +1400,8 @@ def generate(env): env['MSVSCLEANCOM'] = '$MSVSSCONSCOM -c "$MSVSBUILDTARGET"' env['MSVSENCODING'] = 'Windows-1252' - try: - version = get_default_visualstudio_version(env) - # keep a record of some of the MSVS info so the user can use it. - dirs = get_msvs_install_dirs(version) - env['MSVS'].update(dirs) - except (SCons.Util.RegError, SCons.Errors.InternalError): - # we don't care if we can't do this -- if we can't, it's - # because we don't have access to the registry, or because the - # tools aren't installed. In either case, the user will have to - # find them on their own. - pass + # Set-up ms tools paths for default version + merge_default_version(env) version_num, suite = msvs_parse_version(env['MSVS_VERSION']) if (version_num < 7.0): @@ -1794,29 +1418,7 @@ def generate(env): env['SCONS_HOME'] = os.environ.get('SCONS_HOME') def exists(env): - if not env['PLATFORM'] in ('win32', 'cygwin'): - return 0 - - try: - v = SCons.Tool.msvs.get_visualstudio_versions() - except (SCons.Util.RegError, SCons.Errors.InternalError): - pass - - if not v: - version_num = 6.0 - if env.has_key('MSVS_VERSION'): - version_num, suite = msvs_parse_version(env['MSVS_VERSION']) - if version_num >= 7.0: - # The executable is 'devenv' in Visual Studio Pro, - # Team System and others. Express Editions have different - # executable names. Right now we're only going to worry - # about Visual C++ 2005 Express Edition. - return env.Detect('devenv') or env.Detect('vcexpress') - else: - return env.Detect('msdev') - else: - # there's at least one version of MSVS installed. - return 1 + return detect_msvs() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index 91a196b..821bbca 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -238,7 +238,7 @@ this dictionary with the following keys: <envar>VERSION</envar>: the version of MSVS being used (can be set via -MSVS_VERSION) +&cv-link-MSVS_VERSION;) <envar>VERSIONS</envar>: the available versions of MSVS installed @@ -274,6 +274,19 @@ If a value isn't set, it wasn't available in the registry. </summary> </cvar> +<cvar name="MSVS_ARCH"> +<summary> +Sets the architecture for which the generated project(s) should build. + +The default value is <literal>x86</literal>. +<literal>amd64</literal> is also supported +by &SCons; for some Visual Studio versions. +Trying to set &cv-MSVS_ARCH; to an architecture that's not +supported for a given Visual Studio version +will generate an error. +</summary> +</cvar> + <cvar name="MSVS_IGNORE_IDE_PATHS"> <summary> Tells the MS Visual Studio tools to use minimal INCLUDE, LIB, and PATH settings, diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 40c6af6..1fb1e75 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -28,11 +28,17 @@ import string import sys import TestCmd import unittest +import copy from SCons.Tool.msvs import * import SCons.Util import SCons.Warnings +from SCons.Tool.MSCommon.common import debug + +from SCons.Tool.MSCommon import get_default_version, \ + query_versions + regdata_6a = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio] [HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0] [HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\ServicePacks] @@ -280,12 +286,75 @@ regdata_8exp = string.split(r''' "VCXDCMakeTool"="*.xdc" ''','\n') +regdata_80 = string.split(r''' +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0] +"CLR Version"="v2.0.50727" +"ApplicationID"="VisualStudio" +"ThisVersionDTECLSID"="{BA018599-1DB3-44f9-83B4-461454C84BF8}" +"ThisVersionSolutionCLSID"="{1B2EEDD6-C203-4d04-BD59-78906E3E8AAB}" +"SecurityAppID"="{DF99D4F5-9F04-4CEF-9D39-095821B49C77}" +"InstallDir"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\" +"EnablePreloadCLR"=dword:00000001 +"RestoreAppPath"=dword:00000001 +"Source Directories"="C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\;C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\;C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\atl\;C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\InstalledProducts] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\InstalledProducts\Microsoft Visual C++] +"UseInterface"=dword:00000001 +"Package"="{F1C25864-3097-11D2-A5C5-00C04F7968B4}" +"DefaultProductAttribute"="VC" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup] +"Dbghelp_path"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\EF] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\EnterpriseFrameworks\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\Microsoft Visual Studio 2005 Professional Edition - ENU] +"SrcPath"="d:\vs\" +"InstallSuccess"=dword:00000001 +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\VC] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\VC\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\VS] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\" +"VS7EnvironmentLocation"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe" +"EnvironmentPath"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe" +"EnvironmentDirectory"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\" +"VS7CommonDir"="C:\Program Files\Microsoft Visual Studio 8\Common7\" +"VS7CommonBinDir"="C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\VS\BuildNumber] +"1033"="8.0.50727.42" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\Setup\VS\Pro] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\VC] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\VC\VC_OBJECTS_PLATFORM_INFO] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32] +@="{72f11281-2429-11d7-8bf6-00b0d03daa06}" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32\ToolDefaultExtensionLists] +"VCCLCompilerTool"="*.cpp;*.cxx;*.cc;*.c" +"VCLinkerTool"="*.obj;*.res;*.lib;*.rsc;*.licenses" +"VCLibrarianTool"="*.obj;*.res;*.lib;*.rsc" +"VCMIDLTool"="*.idl;*.odl" +"VCCustomBuildTool"="*.bat" +"VCResourceCompilerTool"="*.rc" +"VCPreBuildEventTool"="*.bat" +"VCPreLinkEventTool"="*.bat" +"VCPostBuildEventTool"="*.bat" +"VCBscMakeTool"="*.sbr" +"VCFxCopTool"="*.dll;*.exe" +"VCNMakeTool"="" +"VCWebServiceProxyGeneratorTool"="*.discomap" +"VCWebDeploymentTool"="" +"VCALinkTool"="*.resources" +"VCManagedResourceCompilerTool"="*.resx" +"VCXMLDataGeneratorTool"="*.xsd" +"VCManifestTool"="*.manifest" +"VCXDCMakeTool"="*.xdc" +''','\n') + regdata_cv = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] "ProgramFilesDir"="C:\Program Files" "CommonFilesDir"="C:\Program Files\Common Files" "MediaPath"="C:\WINDOWS\Media" ''','\n') + regdata_none = [] class DummyEnv: @@ -314,6 +383,8 @@ class RegKey: def __init__(self,key): self.key = key +# Warning: this is NOT case-insensitive, unlike the Windows registry. +# So e.g. HKLM\Software is NOT the same key as HKLM\SOFTWARE. class RegNode: """node in the dummy registry""" def __init__(self,name): @@ -453,50 +524,60 @@ def DummyExists(path): return 1 class msvsTestCase(unittest.TestCase): + """This test case is run several times with different defaults. + See its subclasses below.""" def setUp(self): global registry registry = self.registry + from SCons.Tool.MSCommon.vs import reset_installed_visual_studios + reset_installed_visual_studios() + + def test_detect_msvs(self): + """Test the detect_msvs() function""" + r = detect_msvs() + assert r == (self.number_of_versions > 0), r - def test_get_default_visual_studio_version(self): + def test_get_default_version(self): """Test retrieval of the default visual studio version""" + + debug("Testing for default version %s"%self.default_version) env = DummyEnv() - v1 = get_default_visualstudio_version(env) - assert env['MSVS_VERSION'] == self.default_version, env['MSVS_VERSION'] - assert env['MSVS']['VERSION'] == self.default_version, env['MSVS']['VERSION'] - assert v1 == self.default_version, v1 + v1 = get_default_version(env) + assert env['MSVS_VERSION'] == self.default_version, \ + (self.default_version, env['MSVS_VERSION']) + assert env['MSVS']['VERSION'] == self.default_version, \ + (self.default_version, env['MSVS']['VERSION']) + assert v1 == self.default_version, (self.default_version, v1) env = DummyEnv({'MSVS_VERSION':'7.0'}) - v2 = get_default_visualstudio_version(env) + v2 = get_default_version(env) assert env['MSVS_VERSION'] == '7.0', env['MSVS_VERSION'] assert env['MSVS']['VERSION'] == '7.0', env['MSVS']['VERSION'] assert v2 == '7.0', v2 env = DummyEnv() - v3 = get_default_visualstudio_version(env) + v3 = get_default_version(env) if v3 == '7.1': override = '7.0' else: override = '7.1' env['MSVS_VERSION'] = override - v3 = get_default_visualstudio_version(env) + v3 = get_default_version(env) assert env['MSVS_VERSION'] == override, env['MSVS_VERSION'] assert env['MSVS']['VERSION'] == override, env['MSVS']['VERSION'] assert v3 == override, v3 - def test_get_visual_studio_versions(self): + def _TODO_test_merge_default_version(self): + """Test the merge_default_version() function""" + pass + + def test_query_versions(self): """Test retrieval of the list of visual studio versions""" - v1 = get_visualstudio_versions() - assert not v1 or v1[0] == self.highest_version, v1 + v1 = query_versions() + assert not v1 or str(v1[0]) == self.highest_version, \ + (v1, self.highest_version) assert len(v1) == self.number_of_versions, v1 - def test_get_msvs_install_dirs(self): - """Test retrieval of the list of visual studio installed locations""" - v1 = get_msvs_install_dirs() - assert v1 == self.default_install_loc, v1 - for key, loc in self.install_locs.items(): - v2 = get_msvs_install_dirs(key) - assert v2 == loc, key + ': ' + str(v2) - class msvs6aTestCase(msvsTestCase): """Test MSVS 6 Registry""" registry = DummyRegistry(regdata_6a + regdata_cv) @@ -504,7 +585,7 @@ class msvs6aTestCase(msvsTestCase): highest_version = '6.0' number_of_versions = 1 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio\\VC98'}, + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio\\VC98', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio\\VC98\\Bin'}, '7.0' : {}, '7.1' : {}, '8.0' : {}, @@ -519,7 +600,7 @@ class msvs6bTestCase(msvsTestCase): highest_version = '6.0' number_of_versions = 1 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\VS6', 'VCINSTALLDIR': 'C:\\VS6\\VC98'}, + '6.0' : {'VSINSTALLDIR': 'C:\\VS6\\VC98', 'VCINSTALLDIR': 'C:\\VS6\\VC98\\Bin'}, '7.0' : {}, '7.1' : {}, '8.0' : {}, @@ -534,8 +615,8 @@ class msvs6and7TestCase(msvsTestCase): highest_version = '7.0' number_of_versions = 2 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\VS6', 'VCINSTALLDIR': 'C:\\VS6\\VC98'}, - '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'}, + '6.0' : {'VSINSTALLDIR': 'C:\\VS6\\VC98', 'VCINSTALLDIR': 'C:\\VS6\\VC98\\Bin'}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, '7.1' : {}, '8.0' : {}, '8.0Exp' : {}, @@ -549,8 +630,8 @@ class msvs7TestCase(msvsTestCase): highest_version = '7.0' number_of_versions = 1 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, - '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'}, + '6.0' : {}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, '7.1' : {}, '8.0' : {}, '8.0Exp' : {}, @@ -564,37 +645,52 @@ class msvs71TestCase(msvsTestCase): highest_version = '7.1' number_of_versions = 1 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '6.0' : {}, '7.0' : {}, - '7.1' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Vc7\\'}, + '7.1' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\Tools'}, '8.0' : {}, '8.0Exp' : {}, } default_install_loc = install_locs['7.1'] -class msvs8ExpTestCase(msvsTestCase): +class msvs8ExpTestCase(msvsTestCase): # XXX: only one still not working """Test MSVS 8 Express Registry""" registry = DummyRegistry(regdata_8exp + regdata_cv) default_version = '8.0Exp' highest_version = '8.0Exp' number_of_versions = 1 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '6.0' : {}, '7.0' : {}, '7.1' : {}, - '8.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\'}, - '8.0Exp' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\'}, + '8.0' : {}, + '8.0Exp' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, } default_install_loc = install_locs['8.0Exp'] +class msvs80TestCase(msvsTestCase): + """Test MSVS 8 Registry""" + registry = DummyRegistry(regdata_80 + regdata_cv) + default_version = '8.0' + highest_version = '8.0' + number_of_versions = 1 + install_locs = { + '6.0' : {}, + '7.0' : {}, + '7.1' : {}, + '8.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['8.0'] + class msvsEmptyTestCase(msvsTestCase): """Test Empty Registry""" registry = DummyRegistry(regdata_none) - default_version = '6.0' + default_version = '9.0' highest_version = None number_of_versions = 0 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '6.0' : {}, '7.0' : {}, '7.1' : {}, '8.0' : {}, @@ -614,6 +710,8 @@ if __name__ == "__main__": SCons.Util.RegEnumValue = DummyEnumValue SCons.Util.RegQueryValueEx = DummyQueryValue os.path.exists = DummyExists # make sure all files exist :-) + os.path.isfile = DummyExists # make sure all files are files :-) + os.path.isdir = DummyExists # make sure all dirs are dirs :-) exit_val = 0 @@ -624,14 +722,28 @@ if __name__ == "__main__": msvs7TestCase, msvs71TestCase, msvs8ExpTestCase, + msvs80TestCase, msvsEmptyTestCase, ] for test_class in test_classes: - print test_class.__doc__ - suite = unittest.makeSuite(test_class, 'test_') - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - exit_val = 1 + print "TEST: ", test_class.__doc__ + back_osenv = copy.deepcopy(os.environ) + try: + # XXX: overriding the os.environ is bad, but doing it + # correctly is too complicated for now. Those tests should + # be fixed + for k in ['VS71COMNTOOLS', + 'VS80COMNTOOLS', + 'VS90COMNTOOLS']: + if os.environ.has_key(k): + del os.environ[k] + + suite = unittest.makeSuite(test_class, 'test_') + if not unittest.TextTestRunner().run(suite).wasSuccessful(): + exit_val = 1 + finally: + os.env = back_osenv sys.exit(exit_val) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index d0f08a6..c77ee49 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -727,10 +727,32 @@ if can_read_reg: # I would use os.path.split here, but it's not a filesystem # path... p = key.rfind('\\') + 1 - keyp = key[:p] + keyp = key[:p-1] # -1 to omit trailing slash val = key[p:] k = RegOpenKeyEx(root, keyp) return RegQueryValueEx(k,val) +else: + try: + e = WindowsError + except NameError: + # Make sure we have a definition of WindowsError so we can + # run platform-independent tests of Windows functionality on + # platforms other than Windows. (WindowsError is, in fact, an + # OSError subclass on Windows.) + class WindowsError(OSError): + pass + import __builtin__ + __builtin__.WindowsError = WindowsError + else: + del e + + HKEY_CLASSES_ROOT = None + HKEY_LOCAL_MACHINE = None + HKEY_CURRENT_USER = None + HKEY_USERS = None + + def RegGetValue(root, key): + raise WindowsError if sys.platform == 'win32': diff --git a/src/setup.py b/src/setup.py index b494b7c..9378770 100644 --- a/src/setup.py +++ b/src/setup.py @@ -401,6 +401,7 @@ arguments = { "SCons.Scanner", "SCons.Script", "SCons.Tool", + "SCons.Tool.MSCommon", "SCons.Tool.packaging", "SCons.Variables", ], diff --git a/test/Delete.py b/test/Delete.py index a7a3062..20dc889 100644 --- a/test/Delete.py +++ b/test/Delete.py @@ -181,6 +181,7 @@ test.run(status=2, stderr=None) fail_strings = [ "No such file or directory", + "The system cannot find the file specified", "The system cannot find the path specified", ] diff --git a/test/Install/Install.py b/test/Install/Install.py index 8c461a7..ac84398 100644 --- a/test/Install/Install.py +++ b/test/Install/Install.py @@ -134,15 +134,15 @@ test.write(['work', 'f1.in'], "f1.in again again\n") os.chmod(test.workpath('work', 'export'), 0555) f = open(f1_out, 'rb') -expect = """\ -scons: *** [%s] %s: Permission denied -""" % (os.path.join('export', 'f1.out'), - test.workpath('work', 'export', 'f1.out')) - -test.run(chdir = 'work', - arguments = f1_out, - stderr=expect, - status=2) + +expect = [ + "Permission denied", + "The process cannot access the file because it is being used by another process", +] + +test.run(chdir = 'work', arguments = f1_out, stderr=None, status=2) + +test.must_contain_any_line(test.stderr(), expect) f.close() diff --git a/test/M4/M4.py b/test/M4/M4.py index d12bb28..44cda7c 100644 --- a/test/M4/M4.py +++ b/test/M4/M4.py @@ -48,7 +48,8 @@ sys.exit(0) """) test.write('SConstruct', """ -env = Environment(M4 = r'%(_python_)s mym4.py', tools=['default', 'm4']) +env = Environment(tools=['default', 'm4'], + M4 = r'%(_python_)s mym4.py') env.M4(target = 'aaa.x', source = 'aaa.x.m4') """ % locals()) @@ -77,9 +78,11 @@ os.system(string.join(sys.argv[1:], " ")) """ % string.replace(test.workpath('wrapper.out'), '\\', '\\\\')) test.write('SConstruct', """ -foo = Environment(M4=r'%(m4)s', M4FLAGS='-DFFF=fff') +foo = Environment(tools=['default', 'm4'], + M4=r'%(m4)s', M4FLAGS='-DFFF=fff') m4 = foo.Dictionary('M4') -bar = Environment(M4 = r'%(_python_)s wrapper.py ' + m4, M4FLAGS='-DBBB=bbb') +bar = Environment(tools=['default', 'm4'], + M4 = r'%(_python_)s wrapper.py ' + m4, M4FLAGS='-DBBB=bbb') foo.M4(target = 'foo.x', source = 'foo.x.m4') bar.M4(target = 'bar', source = 'bar.m4') """ % locals()) diff --git a/test/MSVC/PCHSTOP-errors.py b/test/MSVC/PCHSTOP-errors.py index 6ffd11a..a460283 100644 --- a/test/MSVC/PCHSTOP-errors.py +++ b/test/MSVC/PCHSTOP-errors.py @@ -56,8 +56,7 @@ env.Program('test', 'test.cpp') expect_stderr = r''' scons: \*\*\* The PCHSTOP construction must be defined if PCH is defined. -File "%s", line \d+, in \? -''' % re.escape(SConstruct_path) +''' + TestSCons.file_expr test.run(arguments='SET_PCHSTOP=0', status=2, stderr=expect_stderr) @@ -65,8 +64,7 @@ test.run(arguments='SET_PCHSTOP=0', status=2, stderr=expect_stderr) expect_stderr = r''' scons: \*\*\* The PCHSTOP construction variable must be a string: .+ -File "%s", line \d+, in \? -''' % re.escape(SConstruct_path) +''' + TestSCons.file_expr test.run(arguments='SET_PCHSTOP=1', status=2, stderr=expect_stderr) diff --git a/test/MSVC/msvc.py b/test/MSVC/msvc.py index c8fa8dc..e28a87f 100644 --- a/test/MSVC/msvc.py +++ b/test/MSVC/msvc.py @@ -180,7 +180,7 @@ test.run(arguments='slow.obj', stderr=None) slow = time.time() - start # using precompiled headers should be faster -limit = slow*0.85 +limit = slow*0.90 if fast >= limit: print "Using precompiled headers was not fast enough:" print "slow.obj: %.3fs" % slow diff --git a/test/MSVC/query_vcbat.py b/test/MSVC/query_vcbat.py new file mode 100644 index 0000000..a662008 --- /dev/null +++ b/test/MSVC/query_vcbat.py @@ -0,0 +1,66 @@ +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import sys + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re) + +if sys.platform != 'win32': + msg = "Skipping Visual C/C++ test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) + +##### +# Test the basics + +test.write('SConstruct', """ +#from SCons.Tool.MSCommon.misc import FindMSVSBatFile, \\ +# ParseBatFile, \\ +# MergeMSVSBatFile +from SCons.Tool.MSCommon import query_versions +#env = Environment(tools = ['mingw']) +DefaultEnvironment(tools = []) +#for v in [9, 8, 7.1, 7]: +# print " ==== Testing for version %s ==== " % str(v) +# bat = FindMSVSBatFile(v) +# print bat +# if bat: +# d = ParseBatFile(bat) +# for k, v in d.items(): +# print k, v +#MergeMSVSBatFile(env, 9.0) +#print env['ENV']['PATH'] +print query_versions() +""") + +test.run(stderr = None) +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: |