Commits

Steven Knight  committed b59424a

Have Visual Studio echo that we're using SCons to build things, to work around a quoting issue. (Shannon Mann)

  • Participants
  • Parent commits a5f4f6c

Comments (0)

Files changed (18)

File etc/TestCmd.py

 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
 __author__ = "Steven Knight <knight at baldmt dot com>"
-__revision__ = "TestCmd.py 0.15.D001 2005/08/16 17:14:33 knight"
-__version__ = "0.15"
+__revision__ = "TestCmd.py 0.16.D002 2005/08/19 16:58:31 knight"
+__version__ = "0.16"
 
 import os
 import os.path
 
 tempfile.template = 'testcmd.'
 
+re_space = re.compile('\s')
+
 if os.name == 'posix':
 
-    def escape_cmd(arg):
+    def escape(arg):
         "escape shell special characters"
         slash = '\\'
         special = '"$'
         for c in special:
             arg = string.replace(arg, c, slash+c)
 
-        return '"' + arg + '"'
+        if re_space.search(arg):
+            arg = '"' + arg + '"'
+        return arg
 
 else:
 
     # Windows does not allow special characters in file names
     # anyway, so no need for an escape function, we will just quote
     # the arg.
-    escape_cmd = lambda x: '"' + x + '"'
+    def escape(arg):
+        if re_space.search(arg):
+            arg = '"' + arg + '"'
+        return arg
 
 _Cleanup = []
 
         """Runs a test of the program or script for the test
         environment.  Standard output and error output are saved for
         future retrieval via the stdout() and stderr() methods.
+
+        The specified program will have the original directory
+        prepending unless it is enclosed in a [list].
         """
         if chdir:
             oldcwd = os.getcwd()
                 sys.stderr.write("chdir(" + chdir + ")\n")
             os.chdir(chdir)
         if program:
-            if not os.path.isabs(program):
+            if type(program) == type('') and not os.path.isabs(program):
                 program = os.path.join(self._cwd, program)
         else:
             program = self.program
             if not interpreter:
                 interpreter = self.interpreter
-        cmd = [program]
+        if type(program) != type([]):
+            program = [program]
+        cmd = program
         if interpreter:
             cmd = [interpreter] + cmd
         if arguments:
             if type(arguments) == type(''):
                 arguments = string.split(arguments)
             cmd.extend(arguments)
-        cmd_string = string.join(cmd, ' ')
+        cmd_string = string.join(map(escape, cmd), ' ')
         if self.verbose:
             sys.stderr.write(cmd_string + "\n")
         try:
             p = popen2.Popen3(cmd, 1)
         except AttributeError:
-            (tochild, fromchild, childerr) = os.popen3(cmd_string)
+            (tochild, fromchild, childerr) = os.popen3(' ' + cmd_string)
             if stdin:
                 if is_List(stdin):
                     for line in stdin:

File etc/TestSCons.py

 attributes defined in this subclass.
 """
 
-# Copyright 2001, 2002, 2003 Steven Knight
+# __COPYRIGHT__
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 SConscript( sconscript )
 """ % (self.QT, self.QT_LIB, self.QT_MOC, self.QT_UIC))
 
+    def msvs_versions(self):
+        if not hasattr(self, '_msvs_versions'):
+
+            # Determine the SCons version and the versions of the MSVS
+            # environments installed on the test machine.
+            #
+            # We do this by executing SCons with an SConstruct file
+            # (piped on stdin) that spits out Python assignments that
+            # we can just exec().  We construct the SCons.__"version"__
+            # string in the input here so that the SCons build itself
+            # doesn't fill it in when packaging SCons.
+            input = """\
+import SCons
+print "self._scons_version =", repr(SCons.__%s__)
+env = Environment();
+print "self._msvs_versions =", str(env['MSVS']['VERSIONS'])
+""" % 'version'
+        
+            self.run(arguments = '-n -q -Q -f -', stdin = input)
+            exec(self.stdout())
+
+        return self._msvs_versions
+
+    def vcproj_sys_path(self, fname):
+        """
+        """
+        orig = 'sys.path = [ join(sys'
+
+        enginepath = repr(os.path.join(self._cwd, '..', 'engine'))
+        replace = 'sys.path = [ %s, join(sys' % enginepath
+
+        contents = self.read(fname)
+        contents = string.replace(contents, orig, replace)
+        self.write(fname, contents)
+
+    def msvs_substitute(self, input, msvs_ver, python=sys.executable):
+        if not hasattr(self, '_msvs_versions'):
+            self.msvs_versions()
+
+        if msvs_ver in ['7.1']:
+            python = '&quot;' + python + '&quot;'
+
+        exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-%s'), join(sys.prefix, 'scons-%s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % (self._scons_version, self._scons_version)
+        exec_script_main_xml = string.replace(exec_script_main, "'", "&apos;")
+
+        result = string.replace(input, r'<WORKPATH>', self.workpath())
+        result = string.replace(result, r'<PYTHON>', python)
+        result = string.replace(result, r'<SCONS_SCRIPT_MAIN>', exec_script_main)
+        result = string.replace(result, r'<SCONS_SCRIPT_MAIN_XML>', exec_script_main_xml)
+        return result
+
 # In some environments, $AR will generate a warning message to stderr
 # if the library doesn't previously exist and is being created.  One
 # way to fix this is to tell AR to be quiet (sometimes the 'c' flag),

File src/CHANGES.txt

   - Fix a bad use of Copy() in an example in the man page, and a
     bad regular expression example in the man page and User's Guide.
 
+  From Shannon Mann:
+
+  - Have the Visual Studio project file(s) echo "Starting SCons" before
+    executing SCons, mainly to work around a quote-stripping bug in
+    (some versions of?) the Windows cmd command executor.
+
   From Michael McCracken:
 
   - Add a new "applelink" tool to handle the things like Frameworks and

File src/engine/SCons/Node/FS.py

             path_orig = [ path_first, ] + path_orig
             path_norm = [ _my_normcase(path_first), ] + path_norm
         else:
+            drive = _my_normcase(drive)
             # Absolute path
             try:
                 directory = self.Root[drive]
             except KeyError:
                 if not create:
                     raise SCons.Errors.UserError
-                directory = RootDir(_my_normcase(drive), self)
+                directory = RootDir(drive, self)
                 self.Root[drive] = directory
 
         if not path_orig:

File src/engine/SCons/SConsign.py

     sig_files = []
     DB_sync_list = []
 
-if os.sep == '/':
-    norm_entry = lambda s: s
-else:
-    def norm_entry(str):
-        return string.replace(str, os.sep, '/')
+normcase = os.path.normcase
 
 def write():
     global sig_files
         # Read using the path relative to the top of the Repository
         # (self.dir.tpath) from which we're fetching the signature
         # information.
-        path = norm_entry(dir.tpath)
+        path = normcase(dir.tpath)
         try:
             rawentries = db[path]
         except KeyError:
         # directory (self.dir.path), not relative to the top of
         # the Repository; we only write to our own .sconsign file,
         # not to .sconsign files in Repositories.
-        path = norm_entry(self.dir.path)
+        path = normcase(self.dir.path)
         for key, entry in self.entries.items():
             entry.convert_to_sconsign()
         db[path] = cPickle.dumps(self.entries, 1)

File src/engine/SCons/Tool/msvs.py

                 self.file.write('# PROP %sOutput_Dir "%s"\n'
                                 '# PROP %sIntermediate_Dir "%s"\n' % (base,outdir,base,outdir))
                 (d,c) = os.path.split(str(self.conspath))
-                cmd = '"%s" -c "%s" -C %s -f %s %s' % (python_executable,
-                                                       exec_script_main,
-                                                       d, c, buildtarget)
+                cmd = 'echo Starting SCons && "%s" -c "%s" -C %s -f %s %s'
+                cmd = cmd % (python_executable, exec_script_main, d, c, buildtarget)
                 self.file.write('# PROP %sCmd_Line "%s"\n' 
                                 '# PROP %sRebuild_Opt "-c && %s"\n'
                                 '# PROP %sTarget_File "%s"\n'
             buildtarget = self.configs[kind].buildtarget
 
             (d,c) = os.path.split(str(self.conspath))
-            cmd = '&quot;%s&quot; -c &quot;%s&quot; -C %s -f %s %s' % (python_executable,
+            cmd = 'echo Starting SCons &amp;&amp; &quot;%s&quot; -c &quot;%s&quot; -C %s -f %s %s' % (python_executable,
                                                    exec_script_main_xml,
                                                    d, c, buildtarget)
 
-            cleancmd = '&quot;%s&quot; -c &quot;%s&quot; -C %s -f %s -c %s' % (python_executable,
+            cleancmd = 'echo Starting SCons &amp;&amp; &quot;%s&quot; -c &quot;%s&quot; -C %s -f %s -c %s' % (python_executable,
                                                          exec_script_main_xml,
                                                          d, c, buildtarget)
 

File test/Case.py

 """)
 
 if sys.platform in ['cygwin', 'win32']:
-    print "Using case-insensitive filesystem, testing for failure"
+    sys.stdout.write("Using case-insensitive filesystem, testing for failure\n")
+    sys.stdout.flush()
 
     test.run(stderr = None, status = None)
     test.fail_test(string.split(test.stderr(), '\n')[0] ==
                    "scons: *** Multiple ways to build the same target were specified for: foo.o")
 
-    test.pass_test()
-    
 else:
-    print "Not using case-insensitive filesystem, testing for success"
+    sys.stdout.write("Not using case-insensitive filesystem, testing for success\n")
+    sys.stdout.flush()
 
     test.run()
     test.run(program = test.workpath('main' + _exe), stdout = "foo\nbar\n")
 
-    test.pass_test()
+test.pass_test()

File test/Configure.py

         print test.stdout()
         print "---------------------------------------------------------"
         test.fail_test()
-    
-
-    test.pass_test()
 
 finally:
     pass
     #print test.read( test.workpath(work_dir, 'config.log'))
     #print "-------------build/config.log------------"
     #print test.read( test.workpath('build/config.log' ))
+
+
+test.pass_test()

File test/IDL/midl.py

 test = TestSCons.TestSCons(match = TestCmd.match_re)
 
 if sys.platform != 'win32':
-    test.pass_test()
+    msg = "Skipping test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
 
 #####
 # Test the basics

File test/MSVC/msvc.py

 test = TestSCons.TestSCons(match = TestCmd.match_re)
 
 if sys.platform != 'win32':
-    test.pass_test()
+    msg = "Skipping Visual C/C++ test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
 
 #####
 # Test the basics

File test/MSVS/vs-6.0.py

+#!/usr/bin/env python
+#
+# __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 os
+import os.path
+import string
+import sys
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestCmd.match_re)
+
+if sys.platform != 'win32':
+    msg = "Skipping Visual Studio test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
+
+if not '6.0' in test.msvs_versions():
+    msg = "Visual Studio 6 not installed; skipping test.\n"
+    test.skip_test(msg)
+
+def diff_section(expect, actual):
+    i = 0
+    for x, y in zip(expect, actual):
+        if x != y:
+            return "Actual did not match expect at char %d:\n" \
+                   "    Expect:  %s\n" \
+                   "    Actual:  %s\n" \
+                   % (i, repr(expect[i-20:i+40]), repr(actual[i-20:i+40]))
+        i = i + 1
+    return "Actual matched the expected output???"
+
+expected_dspfile = '''\
+# Microsoft Developer Studio Project File - Name="Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Test.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Test.mak" CFG="Test - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Test - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "<WORKPATH>"
+# PROP BASE Intermediate_Dir "<WORKPATH>"
+# PROP BASE Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP BASE Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP BASE Target_File "<WORKPATH>\Test.exe"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "<WORKPATH>"
+# PROP Intermediate_Dir "<WORKPATH>"
+# PROP Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+# PROP Target_File "<WORKPATH>\Test.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "Test - Win32 Release"
+
+!IF  "$(CFG)" == "Test - Win32 Release"
+
+!ENDIF 
+
+# Begin Group " Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;l;y;def;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="sdk.h"
+# End Source File
+# End Group
+# Begin Group "Local Headers"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="test.h"
+# End Source File
+# End Group
+# Begin Group "Other Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="readme.txt"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE="test.rc"
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE="<WORKPATH>\SConstruct"
+# End Source File
+# End Target
+# End Project
+'''
+
+expected_dswfile = '''\
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Test"="<WORKPATH>\Test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+'''
+
+
+
+test.write('SConstruct','''
+env=Environment(MSVS_VERSION = '6.0')
+
+testsrc = ['test.c']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+env.MSVSProject(target = 'Test.dsp',
+                srcs = testsrc,
+                incs = testincs,
+                localincs = testlocalincs,
+                resources = testresources,
+                misc = testmisc,
+                buildtarget = 'Test.exe',
+                variant = 'Release')
+''')
+
+test.run(arguments="Test.dsp")
+
+test.must_exist(test.workpath('Test.dsp'))
+dsp = test.read('Test.dsp', 'r')
+expect = test.msvs_substitute(expected_dspfile, '6.0')
+# don't compare the pickled data
+assert dsp[:len(expect)] == expect, diff_section(expect, dsp)
+
+test.must_exist(test.workpath('Test.dsw'))
+dsw = test.read('Test.dsw', 'r')
+expect = test.msvs_substitute(expected_dswfile, '6.0')
+assert dsw == expect, diff_section(expect, dsw)
+
+test.run(arguments='-c .')
+
+test.must_not_exist(test.workpath('Test.dsp'))
+test.must_not_exist(test.workpath('Test.dsw'))
+
+test.run(arguments='Test.dsp')
+
+test.must_exist(test.workpath('Test.dsp'))
+test.must_exist(test.workpath('Test.dsw'))
+
+test.run(arguments='-c Test.dsw')
+
+test.must_not_exist(test.workpath('Test.dsp'))
+test.must_not_exist(test.workpath('Test.dsw'))
+
+
+
+test.write('SConstruct','''
+env=Environment(MSVS_VERSION = '6.0')
+
+env.MSVSProject(target = 'Test.dsp',
+                srcs = ['test.c'],
+                buildtarget = 'Test.exe',
+                variant = 'Release')
+
+env.Program('test.c')
+''')
+
+test.write('test.c', r"""
+int
+main(int argc, char *argv)
+{
+    printf("test.c\n");
+    exit (0);
+}
+""")
+
+# Let SCons figure out the Visual Studio environment variables for us and
+# print out a statement that we can exec to suck them into our external
+# environment so we can execute msdev and really try to build something.
+
+test.run(arguments = '-n -q -Q -f -', stdin = """\
+env = Environment(tools = ['msvc'])
+print "os.environ.update(%s)" % repr(env['ENV'])
+""")
+
+exec(test.stdout())
+
+test.run(arguments='Test.dsp')
+
+test.run(program=['msdev'],
+         arguments=['Test.dsp', '/MAKE', 'test - Win32 Release'])
+
+test.run(program=test.workpath('test'), stdout = "test.c\n")
+
+
+
+test.pass_test()

File test/MSVS/vs-7.0.py

+#!/usr/bin/env python
+#
+# __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 os
+import os.path
+import sys
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestCmd.match_re)
+
+if sys.platform != 'win32':
+    msg = "Skipping Visual Studio test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
+
+if not '7.0' in test.msvs_versions():
+    msg = "Visual Studio 7.0 not installed; skipping test.\n"
+    test.skip_test(msg)
+
+def diff_section(expect, actual):
+    i = 0
+    for x, y in zip(expect, actual):
+        if x != y:
+            return "Actual did not match expect at char %d:\n" \
+                   "    Expect:  %s\n" \
+                   "    Actual:  %s\n" \
+                   % (i, repr(expect[i-20:i+40]), repr(actual[i-20:i+40]))
+        i = i + 1
+    return "Actual matched the expected output???"
+
+expected_slnfile = """\
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{SLNGUID}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Release
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{SLNGUID}.Release.ActiveCfg = Release|Win32
+		{SLNGUID}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
+"""
+
+expected_vcprojfile = """\
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="Test"
+	SccProjectName=""
+	SccLocalPath=""
+	Keyword="MakeFileProj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="<WORKPATH>"
+			IntermediateDirectory="<WORKPATH>"
+			ConfigurationType="0"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+				CleanCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
+				RebuildCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+				Output="<WORKPATH>\Test.exe"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name=" Source Files"
+			Filter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
+			<File
+				RelativePath="test.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="sdk.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Local Headers"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="test.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Other Files"
+			Filter="">
+			<File
+				RelativePath="readme.txt">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
+			<File
+				RelativePath="test.rc">
+			</File>
+		</Filter>
+		<File
+			RelativePath="<WORKPATH>\SConstruct">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
+"""
+
+test.write('SConstruct', """\
+env=Environment(MSVS_VERSION = '7.0')
+
+testsrc = ['test.cpp']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+env.MSVSProject(target = 'Test.vcproj',
+                slnguid = '{SLNGUID}',
+                srcs = testsrc,
+                incs = testincs,
+                localincs = testlocalincs,
+                resources = testresources,
+                misc = testmisc,
+                buildtarget = 'Test.exe',
+                variant = 'Release')
+""")
+
+test.run(arguments="Test.vcproj")
+
+test.must_exist(test.workpath('Test.vcproj'))
+vcproj = test.read('Test.vcproj', 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, diff_section(expect, vcproj)
+
+test.must_exist(test.workpath('Test.sln'))
+sln = test.read('Test.sln', 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.0')
+# don't compare the pickled data
+assert sln[:len(expect)] == expect, diff_section(expect, sln)
+
+test.run(arguments='-c .')
+
+test.must_not_exist(test.workpath('Test.vcproj'))
+test.must_not_exist(test.workpath('Test.sln'))
+
+test.run(arguments='Test.vcproj')
+
+test.must_exist(test.workpath('Test.vcproj'))
+test.must_exist(test.workpath('Test.sln'))
+
+test.run(arguments='-c Test.sln')
+
+test.must_not_exist(test.workpath('Test.vcproj'))
+test.must_not_exist(test.workpath('Test.sln'))
+
+
+
+# Test that running SCons with $PYTHON_ROOT in the environment
+# changes the .vcproj output as expected.
+os.environ['PYTHON_ROOT'] = 'xyzzy'
+
+test.run(arguments='Test.vcproj')
+
+python = os.path.join('$(PYTHON_ROOT)', os.path.split(sys.executable)[1])
+
+test.must_exist(test.workpath('Test.vcproj'))
+vcproj = test.read('Test.vcproj', 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', python=python)
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, diff_section(expect, vcproj)
+
+os.environ['PYTHON_ROOT'] = ''
+
+
+
+test.write('SConstruct', """\
+env=Environment(MSVS_VERSION = '7.0')
+
+env.MSVSProject(target = 'Test.vcproj',
+                srcs = ['test.c'],
+                buildtarget = 'test.exe',
+                variant = 'Release')
+
+env.Program('test.c')
+""")
+
+test.write('test.c', r"""
+int
+main(int argc, char *argv)
+{
+    printf("test.c\n");
+    exit (0);
+}
+""")
+
+# Let SCons figure out the Visual Studio environment variables for us and
+# print out a statement that we can exec to suck them into our external
+# environment so we can execute devenv and really try to build something.
+
+test.run(arguments = '-n -q -Q -f -', stdin = """\
+env = Environment(tools = ['msvc'])
+print "os.environ.update(%s)" % repr(env['ENV'])
+""")
+
+exec(test.stdout())
+
+test.run(arguments='Test.vcproj')
+
+test.run(program=['devenv'],
+         arguments=['Test.sln', '/build', 'Release'])
+
+test.run(program=test.workpath('test'), stdout = "test.c\n")
+
+
+
+test.pass_test()

File test/MSVS/vs-7.1.py

+#!/usr/bin/env python
+#
+# __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 os
+import os.path
+import string
+import sys
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestCmd.match_re)
+
+if sys.platform != 'win32':
+    msg = "Skipping Visual Studio test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
+
+if not '7.1' in test.msvs_versions():
+    msg = "Visual Studio 7.1 not installed; skipping test.\n"
+    test.skip_test(msg)
+
+def diff_section(expect, actual):
+    i = 0
+    for x, y in zip(expect, actual):
+        if x != y:
+            return "Actual did not match expect at char %d:\n" \
+                   "    Expect:  %s\n" \
+                   "    Actual:  %s\n" \
+                   % (i, repr(expect[i-20:i+40]), repr(actual[i-20:i+40]))
+        i = i + 1
+    return "Actual matched the expected output???"
+
+expected_slnfile = """\
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{SLNGUID}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{SLNGUID}.Release.ActiveCfg = Release|Win32
+		{SLNGUID}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
+"""
+
+expected_vcprojfile = """\
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="Test"
+	SccProjectName=""
+	SccLocalPath=""
+	Keyword="MakeFileProj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="<WORKPATH>"
+			IntermediateDirectory="<WORKPATH>"
+			ConfigurationType="0"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+				CleanCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
+				RebuildCommandLine="echo Starting SCons &amp;&amp; <PYTHON> -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
+				Output="<WORKPATH>\Test.exe"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name=" Source Files"
+			Filter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
+			<File
+				RelativePath="test.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="sdk.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Local Headers"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="test.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Other Files"
+			Filter="">
+			<File
+				RelativePath="readme.txt">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
+			<File
+				RelativePath="test.rc">
+			</File>
+		</Filter>
+		<File
+			RelativePath="<WORKPATH>\SConstruct">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
+"""
+
+test.write('SConstruct', """\
+env=Environment(MSVS_VERSION = '7.1')
+
+testsrc = ['test.cpp']
+testincs = ['sdk.h']
+testlocalincs = ['test.h']
+testresources = ['test.rc']
+testmisc = ['readme.txt']
+
+env.MSVSProject(target = 'Test.vcproj',
+                slnguid = '{SLNGUID}',
+                srcs = testsrc,
+                incs = testincs,
+                localincs = testlocalincs,
+                resources = testresources,
+                misc = testmisc,
+                buildtarget = 'Test.exe',
+                variant = 'Release')
+""")
+
+test.run(arguments="Test.vcproj")
+
+test.must_exist(test.workpath('Test.vcproj'))
+vcproj = test.read('Test.vcproj', 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.1')
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, diff_section(expect, vcproj)
+    
+
+test.must_exist(test.workpath('Test.sln'))
+sln = test.read('Test.sln', 'r')
+expect = test.msvs_substitute(expected_slnfile, '7.1')
+# don't compare the pickled data
+assert sln[:len(expect)] == expect, diff_section(expect, sln)
+
+test.run(arguments='-c .')
+
+test.must_not_exist(test.workpath('Test.vcproj'))
+test.must_not_exist(test.workpath('Test.sln'))
+
+test.run(arguments='Test.vcproj')
+
+test.must_exist(test.workpath('Test.vcproj'))
+test.must_exist(test.workpath('Test.sln'))
+
+test.run(arguments='-c Test.sln')
+
+test.must_not_exist(test.workpath('Test.vcproj'))
+test.must_not_exist(test.workpath('Test.sln'))
+
+
+
+
+# Test that running SCons with $PYTHON_ROOT in the environment
+# changes the .vcproj output as expected.
+os.environ['PYTHON_ROOT'] = 'xyzzy'
+
+test.run(arguments='Test.vcproj')
+
+python = os.path.join('$(PYTHON_ROOT)', os.path.split(sys.executable)[1])
+
+test.must_exist(test.workpath('Test.vcproj'))
+vcproj = test.read('Test.vcproj', 'r')
+expect = test.msvs_substitute(expected_vcprojfile, '7.1', python=python)
+# don't compare the pickled data
+assert vcproj[:len(expect)] == expect, diff_section(expect, vcproj)
+
+os.environ['PYTHON_ROOT'] = ''
+
+
+
+test.write('SConstruct', """\
+env=Environment(MSVS_VERSION = '7.1')
+
+env.MSVSProject(target = 'foo.vcproj',
+                srcs = ['foo.c'],
+                buildtarget = 'foo.exe',
+                variant = 'Release')
+
+t = env.Program('foo.c')
+print "t =", t[0]
+print "t =", t[0].abspath
+import sys
+print sys.argv
+""")
+
+test.write('foo.c', r"""
+int
+main(int argc, char *argv)
+{
+    printf("test.c\n");
+    exit (0);
+}
+""")
+
+# Let SCons figure out the Visual Studio environment variables for us and
+# print out a statement that we can exec to suck them into our external
+# environment so we can execute devenv and really try to build something.
+
+test.run(arguments = '-n -q -Q -f -', stdin = """\
+env = Environment(tools = ['msvc'])
+print "os.environ.update(%s)" % repr(env['ENV'])
+""")
+
+exec(test.stdout())
+
+test.run(arguments='foo.vcproj')
+
+test.vcproj_sys_path('foo.vcproj')
+
+test.run(program=['devenv'],
+         arguments=['foo.sln', '/build', 'Release'])
+
+test.run(program=test.workpath('foo'), stdout = "test.c\n")
+
+
+
+test.pass_test()

File test/bad-drive.py

 test = TestSCons.TestSCons()
 
 if sys.platform != 'win32':
-    test.pass_test()
+    msg = "Skipping drive-letter test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
 
 bad_drive = None
 for i in range(len(string.uppercase)-1, -1, -1):

File test/mingw.py

 
 # MinGW is win32 only:
 if sys.platform != 'win32':
-    test.pass_test()
+    msg = "Skipping mingw test on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
 
 # This test requires MingW to be installed:
 test.write('SConstruct',"""

File test/msvs.py

-#!/usr/bin/env python
-#
-# __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 os
-import os.path
-import re
-import string
-import sys
-import time
-
-import TestCmd
-import TestSCons
-
-expected_dspfile = '''\
-# Microsoft Developer Studio Project File - Name="Test" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) External Target" 0x0106
-
-CFG=Test - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "Test.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "Test.mak" CFG="Test - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "Test - Win32 Release" (based on "Win32 (x86) External Target")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-
-!IF  "$(CFG)" == "Test - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "<WORKPATH>"
-# PROP BASE Intermediate_Dir "<WORKPATH>"
-# PROP BASE Cmd_Line ""<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP BASE Rebuild_Opt "-c && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP BASE Target_File "<WORKPATH>\Test.exe"
-# PROP BASE Bsc_Name ""
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "<WORKPATH>"
-# PROP Intermediate_Dir "<WORKPATH>"
-# PROP Cmd_Line ""<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP Rebuild_Opt "-c && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe"
-# PROP Target_File "<WORKPATH>\Test.exe"
-# PROP Bsc_Name ""
-# PROP Target_Dir ""
-
-!ENDIF
-
-# Begin Target
-
-# Name "Test - Win32 Release"
-
-!IF  "$(CFG)" == "Test - Win32 Release"
-
-!ENDIF 
-
-# Begin Group " Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;l;y;def;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="test.cpp"
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="sdk.h"
-# End Source File
-# End Group
-# Begin Group "Local Headers"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="test.h"
-# End Source File
-# End Group
-# Begin Group "Other Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE="readme.txt"
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE="test.rc"
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE="<WORKPATH>\SConstruct"
-# End Source File
-# End Target
-# End Project
-'''
-
-expected_dswfile = '''\
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "Test"="<WORKPATH>\Test.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-'''
-
-expected_slnfile = '''\
-Microsoft Visual Studio Solution File, Format Version 7.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{SLNGUID}"
-EndProject
-Global
-	GlobalSection(SolutionConfiguration) = preSolution
-		ConfigName.0 = Release
-	EndGlobalSection
-	GlobalSection(ProjectDependencies) = postSolution
-	EndGlobalSection
-	GlobalSection(ProjectConfiguration) = postSolution
-		{SLNGUID}.Release.ActiveCfg = Release|Win32
-		{SLNGUID}.Release.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-	EndGlobalSection
-	GlobalSection(ExtensibilityAddIns) = postSolution
-	EndGlobalSection
-EndGlobal
-'''
-
-expected_vcprojfile = '''\
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="Test"
-	SccProjectName=""
-	SccLocalPath=""
-	Keyword="MakeFileProj">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="<WORKPATH>"
-			IntermediateDirectory="<WORKPATH>"
-			ConfigurationType="0"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
-"
-				CleanCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct -c <WORKPATH>\Test.exe"
-				RebuildCommandLine="<PYTHON> -c "<SCONS_SCRIPT_MAIN_XML>" -C <WORKPATH> -f SConstruct <WORKPATH>\Test.exe
-"
-				Output="<WORKPATH>\Test.exe"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name=" Source Files"
-			Filter="cpp;c;cxx;l;y;def;odl;idl;hpj;bat">
-			<File
-				RelativePath="test.cpp">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl">
-			<File
-				RelativePath="sdk.h">
-			</File>
-		</Filter>
-		<Filter
-			Name="Local Headers"
-			Filter="h;hpp;hxx;hm;inl">
-			<File
-				RelativePath="test.h">
-			</File>
-		</Filter>
-		<Filter
-			Name="Other Files"
-			Filter="">
-			<File
-				RelativePath="readme.txt">
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
-			<File
-				RelativePath="test.rc">
-			</File>
-		</Filter>
-		<File
-			RelativePath="<WORKPATH>\SConstruct">
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
-'''
-
-test = TestSCons.TestSCons(match = TestCmd.match_re)
-
-if sys.platform != 'win32':
-    test.pass_test()
-
-test.run(arguments = '-q -Q -f -', stdin = "import SCons; print SCons.__version__")
-version = test.stdout()[:-1]
-
-exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-%s'), join(sys.prefix, 'scons-%s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % (version, version)
-exec_script_main_xml = string.replace(exec_script_main, "'", "&apos;")
-
-def substitute(input, workpath=test.workpath(), python=sys.executable):
-    result = string.replace(input, r'<WORKPATH>', workpath)
-    result = string.replace(result, r'<PYTHON>', python)
-    result = string.replace(result, r'<SCONS_SCRIPT_MAIN>', exec_script_main)
-    result = string.replace(result, r'<SCONS_SCRIPT_MAIN_XML>', exec_script_main_xml)
-    return result
-
-####
-# Determine which environments are installed on the test machine.
-test.write('SConstruct','''
-env = Environment()
-
-f = open('versions','w')
-f.write('versions = ' + str(env['MSVS']['VERSIONS']))
-f.close()
-''')
-
-test.run()
-versions = []
-execfile(test.workpath('versions'))
-
-#####
-# Test v6.0 output
-
-if '6.0' in versions:
-    test.write('SConstruct','''
-env=Environment(MSVS_VERSION = '6.0')
-
-testsrc = ['test.cpp']
-testincs = ['sdk.h']
-testlocalincs = ['test.h']
-testresources = ['test.rc']
-testmisc = ['readme.txt']
-
-env.MSVSProject(target = 'Test.dsp',
-                srcs = testsrc,
-                incs = testincs,
-                localincs = testlocalincs,
-                resources = testresources,
-                misc = testmisc,
-                buildtarget = 'Test.exe',
-                variant = 'Release')
-    ''')
-
-    test.run(arguments="Test.dsp")
-
-    test.fail_test(not os.path.exists(test.workpath('Test.dsp')))
-    dsp = test.read('Test.dsp', 'r')
-    expect = substitute(expected_dspfile)
-    # don't compare the pickled data
-    assert dsp[:len(expect)] == expect
-
-    test.fail_test(not os.path.exists(test.workpath('Test.dsw')))
-    dsw = test.read('Test.dsw', 'r')
-    expect = substitute(expected_dswfile)
-    assert dsw == expect
-
-    test.run(arguments='-c .')
-
-    test.fail_test(os.path.exists(test.workpath('Test.dsp')))
-    test.fail_test(os.path.exists(test.workpath('Test.dsw')))
-
-    test.run(arguments='Test.dsp')
-
-    test.fail_test(not os.path.exists(test.workpath('Test.dsp')))
-    test.fail_test(not os.path.exists(test.workpath('Test.dsw')))
-
-    test.run(arguments='-c Test.dsw')
-
-    test.fail_test(os.path.exists(test.workpath('Test.dsp')))
-    test.fail_test(os.path.exists(test.workpath('Test.dsw')))
-
-#####
-# Test .NET output
-
-if '7.0' in versions:
-    test.write('SConstruct','''
-env=Environment(MSVS_VERSION = '7.0')
-
-testsrc = ['test.cpp']
-testincs = ['sdk.h']
-testlocalincs = ['test.h']
-testresources = ['test.rc']
-testmisc = ['readme.txt']
-
-env.MSVSProject(target = 'Test.vcproj',
-                slnguid = '{SLNGUID}',
-                srcs = testsrc,
-                incs = testincs,
-                localincs = testlocalincs,
-                resources = testresources,
-                misc = testmisc,
-                buildtarget = 'Test.exe',
-                variant = 'Release')
-    ''')
-
-    test.run(arguments="Test.vcproj")
-
-    test.fail_test(not os.path.exists(test.workpath('Test.vcproj')))
-    test.read('Test.vcproj', 'r')
-    expect = substitute(expected_vcprojfile)
-    # don't compare the pickled data
-    assert vcproj[:len(expect)] == expect
-
-    test.fail_test(not os.path.exists(test.workpath('Test.sln')))
-    sln = test.read('Test.sln', 'r')
-    expect = substitute(expected_slnfile)
-    # don't compare the pickled data
-    assert sln[:len(expect)] == expect
-
-    test.run(arguments='-c .')
-
-    test.fail_test(os.path.exists(test.workpath('Test.vcproj')))
-    test.fail_test(os.path.exists(test.workpath('Test.sln')))
-
-    test.run(arguments='Test.vcproj')
-
-    test.fail_test(not os.path.exists(test.workpath('Test.vcproj')))
-    test.fail_test(not os.path.exists(test.workpath('Test.sln')))
-
-    test.run(arguments='-c Test.sln')
-
-    test.fail_test(os.path.exists(test.workpath('Test.vcproj')))
-    test.fail_test(os.path.exists(test.workpath('Test.sln')))
-
-    # Test that running SCons with $PYTHON_ROOT in the environment
-    # changes the .vcproj output as expected.
-    os.environ['PYTHON_ROOT'] = 'xyzzy'
-
-    test.run(arguments='Test.vcproj')
-
-    python = os.path.join('$(PYTHON_ROOT)', os.path.split(sys.executable)[1])
-
-    test.fail_test(not os.path.exists(test.workpath('Test.vcproj')))
-    test.read('Test.vcproj', 'r')
-    expect = substitute(expected_vcprojfile, python=python)
-    # don't compare the pickled data
-    assert vcproj[:len(expect)] == expect
-
-test.pass_test()

File test/timestamp-fallback.py

     pass
 else:
     if desc[2] == imp.C_BUILTIN:
-	print "The 'md5' module is built in to this version of Python."
-	print "Cannot test falling back to timestamps."
-        test.pass_test(1);
+        msg = "The 'md5' module is built in to this version of Python.\n" + \
+              "Cannot test falling back to timestamps.\n"
+        test.skip_test(msg)
 
 test.write('md5.py', r"""
 raise ImportError

File test/win32pathmadness.py

 test = TestSCons.TestSCons(match=TestCmd.match_re)
 
 if sys.platform != 'win32':
-    test.pass_test()
+    msg = "Skipping Windows path tests on non-Windows platform '%s'\n" % sys.platform
+    test.skip_test(msg)
 
 test.subdir('src', 'build', 'include', 'src2')
 
 int bar(void);
 """)
 
-drive,rest = os.path.splitdrive(test.workpath('src'))
-upper = os.path.join(string.upper(drive),rest)
-lower = os.path.join(string.lower(drive),rest)
+drive, rest = os.path.splitdrive(test.workpath('src'))
 
-test.run(chdir=upper)
-test.run(chdir=lower, stdout=test.wrap_stdout("""\
+drive_upper = string.upper(drive)
+drive_lower = string.lower(drive)
+rest_upper = rest[0] + string.upper(rest[1]) + rest[2:]
+rest_lower = rest[0] + string.lower(rest[1]) + rest[2:]
+
+combinations = [
+    os.path.join(drive_upper, rest_upper),
+    os.path.join(drive_upper, rest_lower),
+    os.path.join(drive_lower, rest_upper),
+    os.path.join(drive_lower, rest_lower),
+]
+
+test.run(chdir=combinations[0])
+
+for dir in combinations[1:]:
+    test.run(chdir=dir, stdout=test.wrap_stdout("""\
 scons: .* is up to date.
 scons: .* is up to date.
 scons: .* is up to date.
 """))
 
+
+
 test.write('SConstruct', """
 env=Environment()
 env.StaticLibrary('a', 'a.c')