summaryrefslogtreecommitdiffstats
path: root/QMTest/TestSCons.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2006-07-25 02:30:45 (GMT)
committerSteven Knight <knight@baldmt.com>2006-07-25 02:30:45 (GMT)
commitdd9bbc79353ae90b2402c16b1613dad4e502d250 (patch)
tree42f857f72bb4dcab6d876d1f9c73e0a1dd70d8c2 /QMTest/TestSCons.py
parent57fcbbc5d24fb16f988e4fe3294d5d49abef8e2a (diff)
downloadSCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.zip
SCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.tar.gz
SCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.tar.bz2
Merged revisions 1441-1539 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ........ r1441 | stevenknight | 2006-04-22 23:06:53 -0400 (Sat, 22 Apr 2006) | 1 line 0.96.D397 - The scons command, branch 0.96.91. ........ r1442 | stevenknight | 2006-04-27 00:45:12 -0400 (Thu, 27 Apr 2006) | 1 line 0.96.D398 - The scons command, branch 0.96.92. ........ r1443 | stevenknight | 2006-04-27 00:49:25 -0400 (Thu, 27 Apr 2006) | 1 line 0.96.D399 - Taskmaster clean-ups in anticipation of refactoring speedups. ........ r1450 | stevenknight | 2006-05-02 00:04:55 -0400 (Tue, 02 May 2006) | 1 line 0.96.D400 - Fix VC+++ 2005 Express detection. (Atul Varma) Fix parsing Intel C compiler Li ........ r1451 | stevenknight | 2006-05-02 01:14:24 -0400 (Tue, 02 May 2006) | 1 line 0.96.D401 - Enhance ParseConfig() to understand -arch and -isysroot options. (Gary Oberbrun ........ r1458 | stevenknight | 2006-05-02 23:21:04 -0400 (Tue, 02 May 2006) | 1 line 0.96.D402 - Make strfunction handling consistent. (David Gruener) ........ r1459 | stevenknight | 2006-05-02 23:37:08 -0400 (Tue, 02 May 2006) | 1 line 0.96.D403 - Comment out the test of CVS checkout from the old tigris.org repository. ........ r1460 | stevenknight | 2006-05-03 23:47:54 -0400 (Wed, 03 May 2006) | 1 line 0.96.D404 - Preserve white space in display Action string. (David Gruener) ........ r1461 | stevenknight | 2006-05-04 09:16:15 -0400 (Thu, 04 May 2006) | 1 line 0.96.D405 - Add MergeFlags() and AddFlags() methods. (Greg Noel) Support recognizing compi ........ r1462 | stevenknight | 2006-05-04 23:46:53 -0400 (Thu, 04 May 2006) | 1 line 0.96.D406 - Fix stack trace when ParseFlags has a null string. ........ r1464 | stevenknight | 2006-05-05 17:21:27 -0400 (Fri, 05 May 2006) | 1 line 0.96.D408 - Fix the string displayed by InstallAs() when called through the default construc ........ r1465 | stevenknight | 2006-05-05 18:30:28 -0400 (Fri, 05 May 2006) | 1 line 0.96.D409 - Fix test/ParseConfig.py, broken in the previous checkin by ParseFlags() changes. ........ r1466 | stevenknight | 2006-05-05 20:42:35 -0400 (Fri, 05 May 2006) | 1 line 0.96.D407 - Avoid recursive calls to main() in SConf test programs. (Karol Pietrzak) ........ r1467 | stevenknight | 2006-05-06 00:27:21 -0400 (Sat, 06 May 2006) | 1 line 0.96.D410 - Catch errors from commands that ParseConfig() calls. (John Pye) ........ r1468 | stevenknight | 2006-05-06 10:55:38 -0400 (Sat, 06 May 2006) | 1 line 0.96.D411 - Significant taskmaster speedup by using reference counts, not list manipulation. ........ r1469 | stevenknight | 2006-05-06 18:38:02 -0400 (Sat, 06 May 2006) | 1 line 0.96.D413 - TeX improvements. ........ r1471 | stevenknight | 2006-05-07 09:07:58 -0400 (Sun, 07 May 2006) | 2 lines Delete properties interfering with clean .jpg checkout. ........ r1472 | stevenknight | 2006-05-07 09:23:54 -0400 (Sun, 07 May 2006) | 1 line 0.96.D412 - Windows portability fixes for two tests and ParseConfig() execution. ........ r1473 | stevenknight | 2006-05-07 09:30:11 -0400 (Sun, 07 May 2006) | 1 line 0.96.D414 - Various man page and documentation updates. ........ r1474 | stevenknight | 2006-05-07 23:53:12 -0400 (Sun, 07 May 2006) | 1 line 0.96.D415 - Initial infrastructure for executing tests under QMTest. (Stefan Seefeld) ........ r1476 | stevenknight | 2006-05-09 00:03:47 -0400 (Tue, 09 May 2006) | 1 line 0.96.D416 - Fix QMTest infrastructure to avoid listing directories with no tests and to find ........ r1477 | stevenknight | 2006-05-16 06:47:51 -0400 (Tue, 16 May 2006) | 1 line 0.96.D417 - Fix Alias turning Entries into Nodes or Dirs too soon. ........ r1478 | stevenknight | 2006-05-17 08:32:58 -0400 (Wed, 17 May 2006) | 1 line 0.96.D418 - Next QMTest changes (including fixing copyrights). ........ r1479 | stevenknight | 2006-05-18 05:07:06 -0400 (Thu, 18 May 2006) | 1 line 0.96.D419 - Fix DVIPDF tests after recent changes. ........ r1497 | stevenknight | 2006-05-23 08:47:01 -0400 (Tue, 23 May 2006) | 1 line 0.96.D420 - Better error message when trying to build a file from an unknown sufix. (Gary O ........ r1498 | stevenknight | 2006-05-23 09:38:52 -0400 (Tue, 23 May 2006) | 1 line 0.96.D421 - Suppress duplicate entries in latest TeX patch. (Joel B. Mohler) ........ r1499 | stevenknight | 2006-05-23 22:00:06 -0400 (Tue, 23 May 2006) | 1 line 0.96.D422 - Add tests for tuple variable expansion. (Gary Oberbrunner) ........ r1515 | stevenknight | 2006-06-12 06:44:24 -0400 (Mon, 12 Jun 2006) | 1 line 0.96.D423 - More QMTest work: start giving runtest.py its own tests, more functionality for ........ r1517 | stevenknight | 2006-06-21 07:34:30 -0400 (Wed, 21 Jun 2006) | 1 line 0.96.D424 - Move test/Configure.py and test/Options.py to avoid confusion with similarly-nam ........ r1518 | stevenknight | 2006-06-21 12:40:37 -0400 (Wed, 21 Jun 2006) | 1 line 0.96.D425 - Change the QMTest infrastructure to use File naming, not Python. Rename tests w ........ r1533 | stevenknight | 2006-07-23 20:10:08 -0400 (Sun, 23 Jul 2006) | 1 line 0.96.D426 - Fix ramifications of changing when Node disambiguation happens. ........ r1535 | stevenknight | 2006-07-24 06:40:43 -0400 (Mon, 24 Jul 2006) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-1534" from http://scons.tigris.org/svn/scons/trunk ........ r1536 | stevenknight | 2006-07-24 21:45:40 -0400 (Mon, 24 Jul 2006) | 2 lines Remove svnmerge-integrated property to start over. ........ r1538 | stevenknight | 2006-07-24 21:51:32 -0400 (Mon, 24 Jul 2006) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-1440" from http://scons.tigris.org/svn/scons/trunk ........
Diffstat (limited to 'QMTest/TestSCons.py')
-rw-r--r--QMTest/TestSCons.py538
1 files changed, 538 insertions, 0 deletions
diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py
new file mode 100644
index 0000000..0904d31
--- /dev/null
+++ b/QMTest/TestSCons.py
@@ -0,0 +1,538 @@
+"""
+TestSCons.py: a testing framework for the SCons software construction
+tool.
+
+A TestSCons environment object is created via the usual invocation:
+
+ test = TestSCons()
+
+TestScons is a subclass of TestCommon, which is in turn is a subclass
+of TestCmd), and hence has available all of the methods and attributes
+from those classes, as well as any overridden or additional methods or
+attributes defined in this subclass.
+"""
+
+# __COPYRIGHT__
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import os.path
+import string
+import sys
+
+from TestCommon import *
+from TestCommon import __all__
+
+__all__.extend([ 'TestSCons',
+ 'python',
+ '_exe',
+ '_obj',
+ '_shobj',
+ 'lib_',
+ '_lib',
+ 'dll_',
+ '_dll'
+ ])
+
+python = python_executable
+_exe = exe_suffix
+_obj = obj_suffix
+_shobj = shobj_suffix
+_lib = lib_suffix
+lib_ = lib_prefix
+_dll = dll_suffix
+dll_ = dll_prefix
+
+def gccFortranLibs():
+ """Test whether -lfrtbegin is required. This can probably be done in
+ a more reliable way, but using popen3 is relatively efficient."""
+
+ libs = ['g2c']
+
+ try:
+ import popen2
+ stderr = popen2.popen3('gcc -v')[2]
+ except OSError:
+ return libs
+
+ for l in stderr.readlines():
+ list = string.split(l)
+ if len(list) > 3 and list[:2] == ['gcc', 'version']:
+ if list[2][:2] == '3.':
+ libs = ['frtbegin'] + libs
+ break
+ return libs
+
+
+if sys.platform == 'cygwin':
+ # On Cygwin, os.path.normcase() lies, so just report back the
+ # fact that the underlying Win32 OS is case-insensitive.
+ def case_sensitive_suffixes(s1, s2):
+ return 0
+else:
+ def case_sensitive_suffixes(s1, s2):
+ return (os.path.normcase(s1) != os.path.normcase(s2))
+
+
+if sys.platform == 'win32':
+ fortran_lib = gccFortranLibs()
+elif sys.platform == 'cygwin':
+ fortran_lib = gccFortranLibs()
+elif string.find(sys.platform, 'irix') != -1:
+ fortran_lib = ['ftn']
+else:
+ fortran_lib = gccFortranLibs()
+
+
+
+file_expr = r"""File "[^"]*", line \d+, in .+
+"""
+
+# re.escape escapes too much.
+def re_escape(str):
+ for c in ['.', '[', ']', '(', ')', '*', '+', '?']: # Not an exhaustive list.
+ str = string.replace(str, c, '\\' + c)
+ return str
+
+
+
+class TestSCons(TestCommon):
+ """Class for testing SCons.
+
+ This provides a common place for initializing SCons tests,
+ eliminating the need to begin every test with the same repeated
+ initializations.
+ """
+
+ def __init__(self, **kw):
+ """Initialize an SCons testing object.
+
+ If they're not overridden by keyword arguments, this
+ initializes the object with the following default values:
+
+ program = 'scons' if it exists,
+ else 'scons.py'
+ interpreter = 'python'
+ match = match_exact
+ workdir = ''
+
+ The workdir value means that, by default, a temporary workspace
+ directory is created for a TestSCons environment. In addition,
+ this method changes directory (chdir) to the workspace directory,
+ so an explicit "chdir = '.'" on all of the run() method calls
+ is not necessary.
+ """
+ self.orig_cwd = os.getcwd()
+ try:
+ script_dir = os.environ['SCONS_SCRIPT_DIR']
+ except KeyError:
+ pass
+ else:
+ os.chdir(script_dir)
+ if not kw.has_key('program'):
+ kw['program'] = os.environ.get('SCONS')
+ if not kw['program']:
+ if os.path.exists('scons'):
+ kw['program'] = 'scons'
+ else:
+ kw['program'] = 'scons.py'
+ if not kw.has_key('interpreter') and not os.environ.get('SCONS_EXEC'):
+ kw['interpreter'] = [python, '-tt']
+ if not kw.has_key('match'):
+ kw['match'] = match_exact
+ if not kw.has_key('workdir'):
+ kw['workdir'] = ''
+ apply(TestCommon.__init__, [self], kw)
+
+ def Environment(self, ENV=None, *args, **kw):
+ """
+ Return a construction Environment that optionally overrides
+ the default external environment with the specified ENV.
+ """
+ import SCons.Environment
+ import SCons.Errors
+ if not ENV is None:
+ kw['ENV'] = ENV
+ try:
+ return apply(SCons.Environment.Environment, args, kw)
+ except (SCons.Errors.UserError, SCons.Errors.InternalError):
+ return None
+
+ def detect(self, var, prog=None, ENV=None):
+ """
+ Detect a program named 'prog' by first checking the construction
+ variable named 'var' and finally searching the path used by
+ SCons. If either method fails to detect the program, then false
+ is returned, otherwise the full path to prog is returned. If
+ prog is None, then the value of the environment variable will be
+ used as prog.
+ """
+ env = self.Environment(ENV)
+ v = env.subst('$'+var)
+ if not v:
+ return None
+ if prog is None:
+ prog = v
+ if v != prog:
+ return None
+ return env.WhereIs(prog)
+
+ def detect_tool(self, tool, prog=None, ENV=None):
+ """
+ Given a tool (i.e., tool specification that would be passed
+ to the "tools=" parameter of Environment()) and a program that
+ corresponds to that tool, return true if and only if we can find
+ that tool using Environment.Detect().
+
+ By default, prog is set to the value passed into the tools parameter.
+ """
+
+ if not prog:
+ prog = tool
+ env = self.Environment(ENV, tools=[tool])
+ if env is None:
+ return None
+ return env.Detect([prog])
+
+ def where_is(self, prog, path=None):
+ """
+ Given a program, search for it in the specified external PATH,
+ or in the actual external PATH is none is specified.
+ """
+ import SCons.Environment
+ env = SCons.Environment.Environment()
+ if path is None:
+ path = os.environ['PATH']
+ return env.WhereIs(prog, path)
+
+ def wrap_stdout(self, build_str = "", read_str = "", error = 0, cleaning = 0):
+ """Wraps standard output string(s) in the normal
+ "Reading ... done" and "Building ... done" strings
+ """
+ cap,lc = [ ('Build','build'),
+ ('Clean','clean') ][cleaning]
+ if error:
+ term = "scons: %sing terminated because of errors.\n" % lc
+ else:
+ term = "scons: done %sing targets.\n" % lc
+ return "scons: Reading SConscript files ...\n" + \
+ read_str + \
+ "scons: done reading SConscript files.\n" + \
+ "scons: %sing targets ...\n" % cap + \
+ build_str + \
+ term
+
+ def up_to_date(self, options = None, arguments = None, read_str = "", **kw):
+ s = ""
+ for arg in string.split(arguments):
+ s = s + "scons: `%s' is up to date.\n" % arg
+ if options:
+ arguments = options + " " + arguments
+ kw['arguments'] = arguments
+ kw['stdout'] = self.wrap_stdout(read_str = read_str, build_str = s)
+ kw['match'] = self.match_exact
+ apply(self.run, [], kw)
+
+ def not_up_to_date(self, options = None, arguments = None, **kw):
+ """Asserts that none of the targets listed in arguments is
+ up to date, but does not make any assumptions on other targets.
+ This function is most useful in conjunction with the -n option.
+ """
+ s = ""
+ for arg in string.split(arguments):
+ s = s + "(?!scons: `%s' is up to date.)" % arg
+ if options:
+ arguments = options + " " + arguments
+ kw['arguments'] = arguments
+ kw['stdout'] = self.wrap_stdout(build_str="("+s+"[^\n]*\n)*")
+ kw['stdout'] = string.replace(kw['stdout'],'\n','\\n')
+ kw['stdout'] = string.replace(kw['stdout'],'.','\\.')
+ kw['match'] = self.match_re_dotall
+ apply(self.run, [], kw)
+
+ def skip_test(self, message="Skipping test.\n"):
+ """Skips a test.
+
+ Proper test-skipping behavior is dependent on whether we're being
+ executed as part of development of a change under Aegis.
+
+ Technically, skipping a test is a NO RESULT, but Aegis will
+ treat that as a test failure and prevent the change from going
+ to the next step. We don't want to force anyone using Aegis
+ to have to install absolutely every tool used by the tests,
+ so we actually report to Aegis that a skipped test has PASSED
+ so that the workflow isn't held up.
+ """
+ if message:
+ sys.stdout.write(message)
+ sys.stdout.flush()
+ devdir = os.popen("aesub '$dd' 2>/dev/null", "r").read()[:-1]
+ intdir = os.popen("aesub '$intd' 2>/dev/null", "r").read()[:-1]
+ if devdir and self._cwd[:len(devdir)] == devdir or \
+ intdir and self._cwd[:len(intdir)] == intdir:
+ # We're under the development directory for this change,
+ # so this is an Aegis invocation; pass the test (exit 0).
+ self.pass_test()
+ else:
+ # skip=1 means skip this function when showing where this
+ # result came from. They only care about the line where the
+ # script called test.skip_test(), not the line number where
+ # we call test.no_result().
+ self.no_result(skip=1)
+
+ def diff_substr(self, 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???"
+
+ def java_ENV(self):
+ """
+ Return a default external environment that uses a local Java SDK
+ in preference to whatever's found in the default PATH.
+ """
+ import SCons.Environment
+ env = SCons.Environment.Environment()
+ java_path = [
+ '/usr/local/j2sdk1.4.2/bin',
+ '/usr/local/j2sdk1.4.1/bin',
+ '/usr/local/j2sdk1.3.1/bin',
+ '/usr/local/j2sdk1.3.0/bin',
+ '/usr/local/j2sdk1.2.2/bin',
+ '/usr/local/j2sdk1.2/bin',
+ '/usr/local/j2sdk1.1.8/bin',
+ '/usr/local/j2sdk1.1.7/bin',
+ '/usr/local/j2sdk1.1.6/bin',
+ '/usr/local/j2sdk1.1.5/bin',
+ '/usr/local/j2sdk1.1.4/bin',
+ '/usr/local/j2sdk1.1.3/bin',
+ '/usr/local/j2sdk1.1.2/bin',
+ '/usr/local/j2sdk1.1.1/bin',
+ env['ENV']['PATH'],
+ ]
+ env['ENV']['PATH'] = string.join(java_path, os.pathsep)
+ return env['ENV']
+
+ def Qt_dummy_installation(self, dir='qt'):
+ # create a dummy qt installation
+
+ self.subdir( dir, [dir, 'bin'], [dir, 'include'], [dir, 'lib'] )
+
+ self.write([dir, 'bin', 'mymoc.py'], """\
+import getopt
+import sys
+import string
+import re
+cmd_opts, args = getopt.getopt(sys.argv[1:], 'io:', [])
+output = None
+impl = 0
+opt_string = ''
+for opt, arg in cmd_opts:
+ if opt == '-o': output = open(arg, 'wb')
+ elif opt == '-i': impl = 1
+ else: opt_string = opt_string + ' ' + opt
+for a in args:
+ contents = open(a, 'rb').read()
+ subst = r'{ my_qt_symbol( "' + a + '\\\\n" ); }'
+ if impl:
+ contents = re.sub( r'#include.*', '', contents )
+ output.write(string.replace(contents, 'Q_OBJECT', subst))
+output.close()
+sys.exit(0)
+""")
+
+ self.write([dir, 'bin', 'myuic.py'], """\
+import os.path
+import re
+import sys
+import string
+output_arg = 0
+impl_arg = 0
+impl = None
+source = None
+for arg in sys.argv[1:]:
+ if output_arg:
+ output = open(arg, 'wb')
+ output_arg = 0
+ elif impl_arg:
+ impl = arg
+ impl_arg = 0
+ elif arg == "-o":
+ output_arg = 1
+ elif arg == "-impl":
+ impl_arg = 1
+ else:
+ if source:
+ sys.exit(1)
+ source = open(arg, 'rb')
+ sourceFile = arg
+if impl:
+ output.write( '#include "' + impl + '"\\n' )
+ includes = re.findall('<include.*?>(.*?)</include>', source.read())
+ for incFile in includes:
+ # this is valid for ui.h files, at least
+ if os.path.exists(incFile):
+ output.write('#include "' + incFile + '"\\n')
+else:
+ output.write( '#include "my_qobject.h"\\n' + source.read() + " Q_OBJECT \\n" )
+output.close()
+sys.exit(0)
+""" )
+
+ self.write([dir, 'include', 'my_qobject.h'], r"""
+#define Q_OBJECT ;
+void my_qt_symbol(const char *arg);
+""")
+
+ self.write([dir, 'lib', 'my_qobject.cpp'], r"""
+#include "../include/my_qobject.h"
+#include <stdio.h>
+void my_qt_symbol(const char *arg) {
+ printf( arg );
+}
+""")
+
+ self.write(['qt', 'lib', 'SConstruct'], r"""
+env = Environment()
+env.StaticLibrary( 'myqt', 'my_qobject.cpp' )
+""")
+
+ self.run(chdir = self.workpath('qt', 'lib'),
+ arguments = '.',
+ stderr = noisy_ar,
+ match = self.match_re_dotall)
+
+ self.QT = self.workpath(dir)
+ self.QT_LIB = 'myqt'
+ self.QT_MOC = '%s %s' % (python, self.workpath(dir, 'bin', 'mymoc.py'))
+ self.QT_UIC = '%s %s' % (python, self.workpath(dir, 'bin', 'myuic.py'))
+
+ def Qt_create_SConstruct(self, place):
+ if type(place) is type([]):
+ place = apply(test.workpath, place)
+ self.write(place, """\
+if ARGUMENTS.get('noqtdir', 0): QTDIR=None
+else: QTDIR=r'%s'
+env = Environment(QTDIR = QTDIR,
+ QT_LIB = r'%s',
+ QT_MOC = r'%s',
+ QT_UIC = r'%s',
+ tools=['default','qt'])
+dup = 1
+if ARGUMENTS.get('build_dir', 0):
+ if ARGUMENTS.get('chdir', 0):
+ SConscriptChdir(1)
+ else:
+ SConscriptChdir(0)
+ dup=int(ARGUMENTS.get('dup', 1))
+ if dup == 0:
+ builddir = 'build_dup0'
+ env['QT_DEBUG'] = 1
+ else:
+ builddir = 'build'
+ BuildDir(builddir, '.', duplicate=dup)
+ print builddir, dup
+ sconscript = Dir(builddir).File('SConscript')
+else:
+ sconscript = File('SConscript')
+Export("env dup")
+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,
+ subdir=None, sconscript=None,
+ python=sys.executable,
+ project_guid=None):
+ if not hasattr(self, '_msvs_versions'):
+ self.msvs_versions()
+
+ if subdir:
+ workpath = self.workpath(subdir)
+ else:
+ workpath = self.workpath()
+
+ if sconscript is None:
+ sconscript = self.workpath('SConstruct')
+
+ if project_guid is None:
+ project_guid = "{E5466E26-0003-F18B-8F8A-BCD76C86388D}"
+
+ if os.environ.has_key('SCONS_LIB_DIR'):
+ exec_script_main = "from os.path import join; import sys; sys.path = [ r'%s' ] + sys.path; import SCons.Script; SCons.Script.main()" % os.environ['SCONS_LIB_DIR']
+ else:
+ 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>', workpath)
+ result = string.replace(result, r'<PYTHON>', python)
+ result = string.replace(result, r'<SCONSCRIPT>', sconscript)
+ result = string.replace(result, r'<SCONS_SCRIPT_MAIN>', exec_script_main)
+ result = string.replace(result, r'<SCONS_SCRIPT_MAIN_XML>', exec_script_main_xml)
+ result = string.replace(result, r'<PROJECT_GUID>', project_guid)
+ return result
+
+ def get_msvs_executable(self, version):
+ """Returns a full path to the executable (MSDEV or devenv)
+ for the specified version of Visual Studio.
+ """
+ sub_path = {
+ '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'],
+ }
+ from SCons.Tool.msvs import get_msvs_install_dirs
+ vs_path = get_msvs_install_dirs(version)['VSINSTALLDIR']
+ return apply(os.path.join, [vs_path] + sub_path[version])
+
+# 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),
+# but this is difficult to do in a platform-/implementation-specific
+# method. Instead, we will use the following as a stderr match for
+# tests that use AR so that we will view zero or more "ar: creating
+# <file>" messages to be successful executions of the test (see
+# test/AR.py for sample usage).
+
+noisy_ar=r'(ar: creating( archive)? \S+\n?)*'