f1037f672257ba816529ef2bc39565a560bf1469
[senf.git] / senfscons / CompileCheck.py
1 import os, os.path, sys
2 from cStringIO import StringIO
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 = StringIO()
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     for error in out.getvalue().splitlines():
30         elts = error.split(':',2)
31         if len(elts) != 3 : continue
32         filename, line, message = elts
33         if not os.path.exists(filename) : continue
34         try: line = int(line)
35         except ValueError : continue
36         message = message.strip()
37
38         if delay_name and not message.startswith('instantiated from '):
39             print "Passed test '%s': %s" % (delay_name, message)
40             delay_name = None
41             continue
42             
43         filename = os.path.abspath(filename)
44         if filename != source[0].abspath : continue
45
46         for name,lines in tests.iteritems():
47             if line >= lines[0] and line <= lines[1]:
48                 passedTests[name] = 1
49                 if message.startswith('instantiated from '):
50                     delay_name = name
51                 else:
52                     print "Passed test '%s': %s" % (name, message)
53     if delay_name:
54         print "Passed test '%s': <unknown message ??>" % delay_name
55     failedTests = set(tests.iterkeys()) - set(passedTests.iterkeys())
56     if failedTests:
57         for test in failedTests:
58             print "Test '%s' FAILED" % test
59         print
60         print "*** %d tests FAILED" % len(failedTests)
61         if os.path.exists(target[0].abspath):
62             os.unlink(target[0].abspath)
63         return 1
64     file(target[0].abspath,"w").close()
65     return 0
66
67 CompileCheck = Action(CompileCheck)
68
69 def generate(env):
70
71     builder = env.Builder(
72         action = CompileCheck,
73         suffix = '.checked',
74         src_suffix = '.cc',
75         source_scanner = SCons.Scanner.C.CScanner(),
76         single_source=1
77     )
78
79     env.Append(BUILDERS = { 'CompileCheck': builder })
80
81 def exists(env):
82     return True