Call CompileCheck builder from BoostUnitTest
[senf.git] / senfscons / CompileCheck.py
1 import os, os.path, sys
2 import tempfile
3 from SCons.Script import *
4 import SCons.Scanner.C
5
6 def scanTests(f):
7     tests = {}
8     name = start = None
9     linenr= 0
10     for line in f:
11         linenr += 1
12         if line.startswith('COMPILE_FAIL(') and ')' in line:
13             name = line.split('(',1)[-1].split(')',1)[0]
14             start = linenr
15         elif line.startswith('}') and name and start:
16             tests[name] = (start, linenr)
17     return tests
18
19 def CompileCheck(target, source, env):
20     tests = scanTests(file(source[0].abspath))
21     cenv = env.Clone()
22     cenv.Append( CPPDEFINES = [ 'COMPILE_CHECK' ] )
23     out = tempfile.TemporaryFile()
24     cenv['SPAWN'] = lambda sh, escape, cmd, args, env, pspawn=cenv['PSPAWN'], out=out: \
25                     pspawn(sh, escape, cmd, args, env, out, out)
26     Action('$CXXCOM').execute(target, source, cenv)
27     passedTests = {}
28     delay_name = None
29     out.seek(0)
30     for error in out.read().splitlines():
31         elts = error.split(':',2)
32         if len(elts) != 3 : continue
33         filename, line, message = elts
34         if not os.path.exists(filename) : continue
35         try: line = int(line)
36         except ValueError : continue
37         message = message.strip()
38
39         if delay_name and not message.startswith('instantiated from '):
40             print "Passed test '%s': %s" % (delay_name, message)
41             delay_name = None
42             continue
43             
44         filename = os.path.abspath(filename)
45         if filename != source[0].abspath : continue
46
47         for name,lines in tests.iteritems():
48             if line >= lines[0] and line <= lines[1]:
49                 passedTests[name] = 1
50                 if message.startswith('instantiated from '):
51                     delay_name = name
52                 else:
53                     print "Passed test '%s': %s" % (name, message)
54     if delay_name:
55         print "Passed test '%s': <unknown message ??>" % delay_name
56     failedTests = set(tests.iterkeys()) - set(passedTests.iterkeys())
57     if failedTests:
58         for test in failedTests:
59             print "Test '%s' FAILED" % test
60         print
61         print "*** %d tests FAILED" % len(failedTests)
62         if os.path.exists(target[0].abspath):
63             os.unlink(target[0].abspath)
64         return 1
65     file(target[0].abspath,"w").close()
66     return 0
67
68 CompileCheck = Action(CompileCheck)
69
70 def generate(env):
71
72     builder = env.Builder(
73         action = CompileCheck,
74         suffix = '.checked',
75         src_suffix = '.cc',
76         source_scanner = SCons.Scanner.C.CScanner(),
77         single_source=1
78     )
79
80     env.Append(BUILDERS = { 'CompileCheck': builder })
81
82 def exists(env):
83     return True