site_scons: added option to overwrite TEST_EXTRA_LIBS in BoostUnitTest target
[senf.git] / site_scons / site_tools / Boost.py
index bc6e0e6..d040b78 100644 (file)
@@ -6,6 +6,7 @@ import os
 import sys
 import tempfile
 import SCons.Scanner.C
+import CustomTests
 
 # ARGH ... Why do they put a '+' in the module name ????????
 SCons.Tool.cplusplus=getattr(__import__('SCons.Tool.c++', globals(), locals(), []).Tool, 'c++')
@@ -50,7 +51,7 @@ def CompileCheck(target, source, env):
             print "Passed test '%s': %s" % (delay_name, message)
             delay_name = None
             continue
-            
+
         filename = os.path.abspath(filename)
         if filename != source[0].abspath : continue
 
@@ -86,8 +87,8 @@ def BoostUnitTest(env, target=None, source=None,  **kw):
     binnode = target.dir.File('.' + target.name + '.bin')
     stampnode = target.dir.File('.' + target.name + '.stamp')
 
-    bin = env.Program(binnode, source, 
-                      LIBS = env['LIBS'] + [ '$TEST_EXTRA_LIBS' ],
+    bin = env.Program(binnode, source,
+                      LIBS = env['LIBS'] + kw.pop('TEST_EXTRA_LIBS', ['$TEST_EXTRA_LIBS']),
                       _LIBFLAGS = ' -Wl,-Bstatic -l$BOOSTTESTLIB -Wl,-Bdynamic ' + env['_LIBFLAGS'],
                       **kw)
 
@@ -97,7 +98,7 @@ def BoostUnitTest(env, target=None, source=None,  **kw):
 
     alias = env.Command(env.File(target), stamp, [ env.NopAction() ] )
 
-    compileTests = [ src for src in source 
+    compileTests = [ src for src in source
                      if src.suffix in SCons.Tool.cplusplus.CXXSuffixes \
                          and src.exists() \
                          and 'COMPILE_CHECK' in file(str(src)).read() ]
@@ -105,7 +106,7 @@ def BoostUnitTest(env, target=None, source=None,  **kw):
         env.Depends(alias, env.CompileCheck(source = compileTests))
 
     _ALL_TESTS.append(alias)
-        
+
     return alias
 
 def FindAllBoostUnitTests(env, target, source):
@@ -117,9 +118,91 @@ def NopAction(env, target, source):
     def nopstr(target, source, env) : return ''
     return env.Action(nop, nopstr)
 
+ConfTest = CustomTests.ConfTest()
+
+@ConfTest
+def CheckBoostVersion(context,fail=False,min=None,max=None):
+    """Check for boost includes.
+
+Will place the boost version number (BOOST_LIB_VERSION) into the
+BOOST_VERSION environment variable.
+
+Options:
+
+    min/max   compare boost version against given range.
+
+    fail      if fail is set to True, the build will be terminated,
+              when no valid boost includes are found."""
+    if min and max:
+        msg = ' in range %s to %s' % (min,max)
+    elif min:
+        msg = ' at least %s' % min
+    elif max:
+        msg = ' at most %s' % max
+    else:
+        msg = ''
+    context.Message( "Checking boost version%s... " % msg )
+    if context.env.has_key('BOOST_VERSION'):
+        ret = context.env['BOOST_VERSION']
+    else:
+        ret = context.TryRun("#include <boost/version.hpp>\n"
+                             "#include <iostream>\n"
+                             "int main(int, char **)\n"
+                             "{ std::cout << BOOST_LIB_VERSION << std::endl; }",
+                             ".cc")[-1].strip()
+
+    if not ret:
+        msg = "no boost includes found"
+        context.env.Replace( BOOST_VERSION = None )
+    else:
+        context.env.Replace( BOOST_VERSION = ret )
+        msg = ret
+        if min or max:
+            try: version = map(int,ret.split('_'))
+            except ValueError:
+                msg = "[%s] invalid version syntax" % ret
+                ret = None
+            else:
+                if min : ret = ret and (version>=map(int,min.split('_')))
+                if max : ret = ret and (version<=map(int,max.split('_')))
+                msg = '[%s] %s' % (msg, ret and "yes" or "no")
+    context.Result(msg)
+    if fail and not ret : context.env.Fail('No valid boost includes found')
+    return ret
+
+@ConfTest
+def CheckBoostVariants(context, *variants):
+    if not variants : variants = ('','mt')
+    useVariant = None
+    if context.env['BOOST_VARIANT'] is not None:
+        useVariant = context.env['BOOST_VARIANT']
+    try:
+        _env = context.env.Clone()
+        for variant in variants:
+            if variant : variantStr = "'%s'" % variant
+            else       : variantStr = "default"
+            context.Message( "Checking boost %s variant... " % variantStr )
+            context.env.Replace( BOOST_VARIANT=variant )
+            context.env.Append( _LIBFLAGS = ' -Wl,-Bstatic -l$BOOSTTESTLIB  -Wl,-Bdynamic' )
+            ret = context.TryLink("#define BOOST_AUTO_TEST_MAIN\n"
+                                  "#include <boost/test/auto_unit_test.hpp>\n"
+                                  "#include <boost/test/test_tools.hpp>\n"
+                                  "BOOST_AUTO_TEST_CASE(test) { BOOST_CHECK(true); }\n",
+                                  ".cc")
+            context.Result( ret )
+            if ret and useVariant is None:
+                useVariant = variant
+    finally:
+        context.env.Replace(**_env.Dictionary())
+    if useVariant is not None and not context.env.GetOption('no_progress'):
+        print  "Using %s boost variant." % (
+            useVariant and "'%s'" % useVariant or "default")
+    context.env.Replace( BOOST_VARIANT = useVariant )
+    return useVariant
+
 def generate(env):
     env.SetDefault(
-        BOOST_VARIANT     = '',
+        BOOST_VARIANT     = None,
         _BOOST_VARIANT    = '${BOOST_VARIANT and "-" or None}$BOOST_VARIANT',
 
         BOOSTTESTLIB      = 'boost_unit_test_framework$_BOOST_VARIANT',
@@ -129,7 +212,10 @@ def generate(env):
         BOOSTSIGNALSLIB   = 'boost_signals$_BOOST_VARIANT',
 
         BOOSTTESTARGS     = [ '--build_info=yes', '--log_level=test_suite' ],
-    )
+        )
+    env.Append(
+        CUSTOM_TESTS      = ConfTest.tests,
+        )
 
     env['BUILDERS']['BoostUnitTest'] = BoostUnitTest
     env['BUILDERS']['FindAllBoostUnitTests'] = FindAllBoostUnitTests