2 import SCons.Script.SConscript
11 # ARGH ... Why do they put a '+' in the module name ????????
12 SCons.Tool.cplusplus=getattr(__import__('SCons.Tool.c++', globals(), locals(), []).Tool, 'c++')
22 if line.startswith('COMPILE_FAIL(') and ')' in line:
23 name = line.split('(',1)[-1].split(')',1)[0]
25 elif line.startswith('}') and name and start:
26 tests[name] = (start, linenr)
29 def CompileCheck(target, source, env):
30 tests = scanTests(file(source[0].abspath))
32 cenv.Append( CPPDEFINES = [ 'COMPILE_CHECK' ] )
33 out = tempfile.TemporaryFile()
34 cenv['SPAWN'] = lambda sh, escape, cmd, args, env, pspawn=cenv['PSPAWN'], out=out: \
35 pspawn(sh, escape, cmd, args, env, out, out)
36 SCons.Script.Action('$CXXCOM').execute(target, source, cenv)
41 for error in result.splitlines():
42 elts = error.split(':',2)
43 if len(elts) != 3 : continue
44 filename, line, message = elts
45 if not os.path.exists(filename) : continue
47 except ValueError : continue
48 message = message.strip()
50 if delay_name and not message.startswith('instantiated from '):
51 print "Passed test '%s': %s" % (delay_name, message)
55 filename = os.path.abspath(filename)
56 if filename != source[0].abspath : continue
58 for name,lines in tests.iteritems():
59 if line >= lines[0] and line <= lines[1]:
61 if message.startswith('instantiated from '):
64 print "Passed test '%s': %s" % (name, message)
66 print "Passed test '%s': <unknown message ??>" % delay_name
67 failedTests = set(tests.iterkeys()) - set(passedTests.iterkeys())
69 for test in failedTests:
70 print "Test '%s' FAILED" % test
72 print "*** %d tests FAILED" % len(failedTests)
73 if os.path.exists(target[0].abspath):
74 os.unlink(target[0].abspath)
76 file(target[0].abspath,"w").write(result)
79 CompileCheck = SCons.Script.Action(CompileCheck)
81 def BoostUnitTest(env, target=None, source=None, **kw):
84 target = env.arg2nodes(target)[0]
85 source = env.arg2nodes(source)
87 binnode = target.dir.File('.' + target.name + '.bin')
88 stampnode = target.dir.File('.' + target.name + '.stamp')
90 bin = env.Program(binnode, source,
91 LIBS = env['LIBS'] + kw.pop('TEST_EXTRA_LIBS', ['$TEST_EXTRA_LIBS']),
92 _LIBFLAGS = ' -Wl,-Bstatic -l$BOOSTTESTLIB -Wl,-Bdynamic ' + env['_LIBFLAGS'],
95 stamp = env.Command(stampnode, bin,
96 [ './$SOURCE $BOOSTTESTARGS', SCons.Script.Touch('$TARGET')],
99 alias = env.Command(env.File(target), stamp, [ env.NopAction() ] )
101 compileTests = [ src for src in source
102 if src.suffix in SCons.Tool.cplusplus.CXXSuffixes \
104 and 'COMPILE_CHECK' in file(str(src)).read() ]
106 env.Depends(alias, env.CompileCheck(source = compileTests))
108 _ALL_TESTS.append(alias)
112 def FindAllBoostUnitTests(env, target, source):
116 def NopAction(env, target, source):
117 def nop(target, source, env) : return None
118 def nopstr(target, source, env) : return ''
119 return env.Action(nop, nopstr)
121 ConfTest = CustomTests.ConfTest()
124 def CheckBoostVersion(context,fail=False,min=None,max=None):
125 """Check for boost includes.
127 Will place the boost version number (BOOST_LIB_VERSION) into the
128 BOOST_VERSION environment variable.
132 min/max compare boost version against given range.
134 fail if fail is set to True, the build will be terminated,
135 when no valid boost includes are found."""
137 msg = ' in range %s to %s' % (min,max)
139 msg = ' at least %s' % min
141 msg = ' at most %s' % max
144 context.Message( "Checking boost version%s... " % msg )
145 if context.env.has_key('BOOST_VERSION'):
146 ret = context.env['BOOST_VERSION']
148 ret = context.TryRun("#include <boost/version.hpp>\n"
149 "#include <iostream>\n"
150 "int main(int, char **)\n"
151 "{ std::cout << BOOST_LIB_VERSION << std::endl; }",
155 msg = "no boost includes found"
156 context.env.Replace( BOOST_VERSION = None )
158 context.env.Replace( BOOST_VERSION = ret )
161 try: version = map(int,ret.split('_'))
163 msg = "[%s] invalid version syntax" % ret
166 if min : ret = ret and (version>=map(int,min.split('_')))
167 if max : ret = ret and (version<=map(int,max.split('_')))
168 msg = '[%s] %s' % (msg, ret and "yes" or "no")
170 if fail and not ret : context.env.Fail('No valid boost includes found')
174 def CheckBoostVariants(context, *variants):
175 if not variants : variants = ('','mt')
177 if context.env['BOOST_VARIANT'] is not None:
178 useVariant = context.env['BOOST_VARIANT']
180 _env = context.env.Clone()
181 for variant in variants:
182 if variant : variantStr = "'%s'" % variant
183 else : variantStr = "default"
184 context.Message( "Checking boost %s variant... " % variantStr )
185 context.env.Replace( BOOST_VARIANT=variant )
186 context.env.Append( _LIBFLAGS = ' -Wl,-Bstatic -l$BOOSTTESTLIB -Wl,-Bdynamic' )
187 ret = context.TryLink("#define BOOST_AUTO_TEST_MAIN\n"
188 "#include <boost/test/auto_unit_test.hpp>\n"
189 "#include <boost/test/test_tools.hpp>\n"
190 "BOOST_AUTO_TEST_CASE(test) { BOOST_CHECK(true); }\n",
192 context.Result( ret )
193 if ret and useVariant is None:
196 context.env.Replace(**_env.Dictionary())
197 if useVariant is not None and not context.env.GetOption('no_progress'):
198 print "Using %s boost variant." % (
199 useVariant and "'%s'" % useVariant or "default")
200 context.env.Replace( BOOST_VARIANT = useVariant )
201 context.env.Append( HAS_BOOST_SYSTEM = context.sconf.CheckLib('boost_system', language='c++', autoadd=False))
207 BOOST_VARIANT = None,
208 _BOOST_VARIANT = '${BOOST_VARIANT and "-" or None}$BOOST_VARIANT',
210 BOOSTTESTLIB = 'boost_unit_test_framework$_BOOST_VARIANT',
211 BOOSTREGEXLIB = 'boost_regex$_BOOST_VARIANT',
212 BOOSTFSLIB = 'boost_filesystem$_BOOST_VARIANT',
213 BOOSTIOSTREAMSLIB = 'boost_iostreams$_BOOST_VARIANT',
214 BOOSTSIGNALSLIB = 'boost_signals$_BOOST_VARIANT',
215 BOOSTDATETIMELIB = 'boost_date_time$_BOOST_VARIANT',
217 _BOOSTSYSTEMLIB = '${HAS_BOOST_SYSTEM and "boost_system" or ""}',
218 BOOSTSYSTEMLIB = '$_BOOSTSYSTEMLIB',
220 BOOSTTESTARGS = [ '--build_info=yes', '--log_level=test_suite' ],
223 CUSTOM_TESTS = ConfTest.tests,
226 env['BUILDERS']['BoostUnitTest'] = BoostUnitTest
227 env['BUILDERS']['FindAllBoostUnitTests'] = FindAllBoostUnitTests
228 env['BUILDERS']['CompileCheck'] = env.Builder(
229 action = CompileCheck,
232 source_scanner = SCons.Scanner.C.CScanner(),
235 env['BUILDERS']['NopAction'] = NopAction