Rename senfscons to site_scons and move python files arround
[senf.git] / site_scons / site_tools / Boost.py
1 import SCons.Script
2 import SCons.Script.SConscript
3 import SCons.Defaults
4 import os.path
5 import os
6 import sys
7 import tempfile
8 import SCons.Scanner.C
9
10 # ARGH ... Why do they put a '+' in the module name ????????
11 SCons.Tool.cplusplus=getattr(__import__('SCons.Tool.c++', globals(), locals(), []).Tool, 'c++')
12
13 _ALL_TESTS = []
14
15 def scanTests(f):
16     tests = {}
17     name = start = None
18     linenr= 0
19     for line in f:
20         linenr += 1
21         if line.startswith('COMPILE_FAIL(') and ')' in line:
22             name = line.split('(',1)[-1].split(')',1)[0]
23             start = linenr
24         elif line.startswith('}') and name and start:
25             tests[name] = (start, linenr)
26     return tests
27
28 def CompileCheck(target, source, env):
29     tests = scanTests(file(source[0].abspath))
30     cenv = env.Clone()
31     cenv.Append( CPPDEFINES = [ 'COMPILE_CHECK' ] )
32     out = tempfile.TemporaryFile()
33     cenv['SPAWN'] = lambda sh, escape, cmd, args, env, pspawn=cenv['PSPAWN'], out=out: \
34                     pspawn(sh, escape, cmd, args, env, out, out)
35     SCons.Script.Action('$CXXCOM').execute(target, source, cenv)
36     passedTests = {}
37     delay_name = None
38     out.seek(0)
39     for error in out.read().splitlines():
40         elts = error.split(':',2)
41         if len(elts) != 3 : continue
42         filename, line, message = elts
43         if not os.path.exists(filename) : continue
44         try: line = int(line)
45         except ValueError : continue
46         message = message.strip()
47
48         if delay_name and not message.startswith('instantiated from '):
49             print "Passed test '%s': %s" % (delay_name, message)
50             delay_name = None
51             continue
52             
53         filename = os.path.abspath(filename)
54         if filename != source[0].abspath : continue
55
56         for name,lines in tests.iteritems():
57             if line >= lines[0] and line <= lines[1]:
58                 passedTests[name] = 1
59                 if message.startswith('instantiated from '):
60                     delay_name = name
61                 else:
62                     print "Passed test '%s': %s" % (name, message)
63     if delay_name:
64         print "Passed test '%s': <unknown message ??>" % delay_name
65     failedTests = set(tests.iterkeys()) - set(passedTests.iterkeys())
66     if failedTests:
67         for test in failedTests:
68             print "Test '%s' FAILED" % test
69         print
70         print "*** %d tests FAILED" % len(failedTests)
71         if os.path.exists(target[0].abspath):
72             os.unlink(target[0].abspath)
73         return 1
74     file(target[0].abspath,"w").close()
75     return 0
76
77 CompileCheck = SCons.Script.Action(CompileCheck)
78
79 def BoostUnitTest(env, target=None, source=None,  **kw):
80     target = env.arg2nodes(target)[0]
81     source = env.arg2nodes(source)
82
83     binnode = target.dir.File('.' + target.name + '.bin')
84     stampnode = target.dir.File('.' + target.name + '.stamp')
85
86     bin = env.Program(binnode, source, 
87                       LIBS = env['LIBS'] + [ '$TEST_EXTRA_LIBS' ],
88                       _LIBFLAGS = ' -Wl,-Bstatic -l$BOOSTTESTLIB -Wl,-Bdynamic ' + env['_LIBFLAGS'],
89                       **kw)
90
91     stamp = env.Command(stampnode, bin,
92                         [ '$SOURCE $BOOSTTESTARGS',
93                           'touch $TARGET' ],
94                         **kw)
95
96     alias = env.Command(env.File(target), stamp, [])
97
98     compileTests = [ src for src in source 
99                      if src.suffix in SCons.Tool.cplusplus.CXXSuffixes \
100                          and src.exists() \
101                          and 'COMPILE_CHECK' in file(str(src)).read() ]
102     if compileTests:
103         env.Depends(alias, env.CompileCheck(source = compileTests))
104
105     _ALL_TESTS.append(alias)
106         
107     return alias
108
109 def FindAllBoostUnitTests(env, target, source):
110     return _ALL_TESTS
111
112 def generate(env):
113     env.SetDefault(
114         BOOST_VARIANT     = '',
115
116         BOOSTTESTLIB      = 'boost_unit_test_framework$BOOST_VARIANT',
117         BOOSTREGEXLIB     = 'boost_regex$BOOST_VARIANT',
118         BOOSTFSLIB        = 'boost_filesystem$BOOST_VARIANT',
119         BOOSTIOSTREAMSLIB = 'boost_iostreams$BOOST_VARIANT',
120         BOOSTSIGNALSLIB   = 'boost_signals$BOOST_VARIANT',
121
122         BOOSTTESTARGS     = [ '--build_info=yes', '--log_level=test_suite' ],
123     )
124
125     env['BUILDERS']['BoostUnitTest'] = BoostUnitTest
126     env['BUILDERS']['FindAllBoostUnitTests'] = FindAllBoostUnitTests
127     env['BUILDERS']['CompileCheck'] = env.Builder(
128         action = CompileCheck,
129         suffix = '.checked',
130         src_suffix = '.cc',
131         source_scanner = SCons.Scanner.C.CScanner(),
132         single_source=1
133         )
134
135 def exists(env):
136     return True