summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--QMTest/TestSConsMSVS.py31
-rw-r--r--doc/man/scons.11
-rw-r--r--src/CHANGES.txt13
-rw-r--r--src/engine/MANIFEST-xml.in1
-rw-r--r--src/engine/MANIFEST.in6
-rw-r--r--src/engine/SCons/Errors.py3
-rw-r--r--src/engine/SCons/Platform/PlatformTests.py2
-rw-r--r--src/engine/SCons/Platform/win32.py25
-rw-r--r--src/engine/SCons/Tool/MSCommon/TODO5
-rw-r--r--src/engine/SCons/Tool/MSCommon/__init__.py49
-rw-r--r--src/engine/SCons/Tool/MSCommon/common.py177
-rw-r--r--src/engine/SCons/Tool/MSCommon/msvc_changes.txt90
-rw-r--r--src/engine/SCons/Tool/MSCommon/netframework.py84
-rw-r--r--src/engine/SCons/Tool/MSCommon/sdk.py256
-rw-r--r--src/engine/SCons/Tool/MSCommon/vs.py496
-rw-r--r--src/engine/SCons/Tool/linkloc.py13
-rw-r--r--src/engine/SCons/Tool/midl.py12
-rw-r--r--src/engine/SCons/Tool/mslib.py28
-rw-r--r--src/engine/SCons/Tool/mslink.py31
-rw-r--r--src/engine/SCons/Tool/mssdk.py64
-rw-r--r--src/engine/SCons/Tool/mssdk.xml50
-rw-r--r--src/engine/SCons/Tool/msvc.py592
-rw-r--r--src/engine/SCons/Tool/msvs.py408
-rw-r--r--src/engine/SCons/Tool/msvs.xml15
-rw-r--r--src/engine/SCons/Tool/msvsTests.py186
-rw-r--r--src/engine/SCons/Util.py24
-rw-r--r--src/setup.py1
-rw-r--r--test/Delete.py1
-rw-r--r--test/Install/Install.py18
-rw-r--r--test/M4/M4.py9
-rw-r--r--test/MSVC/PCHSTOP-errors.py6
-rw-r--r--test/MSVC/msvc.py2
-rw-r--r--test/MSVC/query_vcbat.py66
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: