X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=site_scons%2Fsenfutil.py;h=f32325444dc96b97aa6f13530d28b84101475eee;hb=84f14a42f9993e186c7897ce0db021300e0a2d48;hp=246f72ed718c9156b5d60500357712a98242d3ac;hpb=42993f284009a951b77718ece3e7a2747041c566;p=senf.git diff --git a/site_scons/senfutil.py b/site_scons/senfutil.py index 246f72e..f323254 100644 --- a/site_scons/senfutil.py +++ b/site_scons/senfutil.py @@ -1,6 +1,8 @@ import os.path, glob, site_tools.Yaptu from SCons.Script import * +import SCons.Defaults, SCons.Util import senfconf +import types, re senfutildir = os.path.dirname(__file__) @@ -32,6 +34,62 @@ class BuildTypeOptions: type = env['final'] and "final" or env['debug'] and "debug" or "normal" return env[self._var + "_" + type] +_DOLLAR_RE = re.compile(r'\$([a-zA-Z_][\.\w]*)|\${([^}]*)}') + +def _expandDefines(defs, target, source, env, for_signature): + rv = [] + if SCons.Util.is_Dict(defs): + keys = defs.keys() + keys.sort() + defs = [ (k,defs[k]) for k in keys ] + elif not SCons.Util.is_List(defs): + defs = [ defs ] + for elt in defs: + if SCons.Util.is_String(elt): + m = _DOLLAR_RE.match(elt) + if m: + match = m.group(1) or m.group(2) + try: rv.extend(_expandDefines(eval(match, env.gvars(), env.lvars()), + target, source, env, for_signature)) + except NameError: pass + except IndexError: pass + else: + rv.append(env.subst(elt)) + elif callable(elt): + rv.extend(_expandDefines(elt(target, source, env, for_signature), + target, source, env, for_signature)) + elif SCons.Util.is_Sequence(elt): + if len(elt)<2 or elt[1] is None: + rv.append(env.subst(elt[0])) + else: + rv.append(env.subst(elt[0]) + "=" + env.subst(elt[1])) + else: + rv.append(str(elt)) + return rv + +def expandDefines(prefix, defs, suffix, env): + """Expand defines in using . Calls SCons.Defaults._concat_ixes +to append prefix/suffix before/after each define. + + callable + Call the callable and replace it with the call result. If the result + is a list, the list is processed recursively. It the result is a + dictionary it is converted into a list of typles and processed + recursively. + '$' or '${}' + Replace the element with the variable expansion. If the result is a + list, the list is processed recursively. It the result is a + dictionary it is converted into a list of typles and processed + recursively. + '' + Define a symbol with that (expanded!) name + iterable + The iteratble must have two elments. The first element defines the + symbol name, the second the symbol value.""" + + defs = _expandDefines(defs, None, None, env, False) + return SCons.Defaults._concat_ixes(prefix, defs, suffix, env) + def loadTools(env): global senfutildir tooldir = os.path.join(senfutildir, 'site_tools') @@ -56,11 +114,14 @@ Special command line parameters: env.Help(vars.GenerateHelpText(env)) try : unknv = vars.UnknownVariables() except AttributeError: unknv = vars.UnknownOptions() + env.SetDefault(ARGUMENT_VARIABLES = {}) for k,v in unknv.iteritems(): if k.endswith('+'): env.Append(**{k[:-1]: v}) + env.Append(ARGUMENT_VARIABLES = {k[:-1]:v}) else: env.Replace(**{k: v}) + env.Append(ARGUMENT_VARIABLES = {k:v}) ########################################################################### @@ -117,6 +178,8 @@ def SetupForSENF(env, senf_path = []): REVISION = "unknown", ) + env.Replace( _defines = expandDefines ) + # Interpret command line options parseArguments( env, @@ -137,6 +200,7 @@ def SetupForSENF(env, senf_path = []): CPPPATH = [ sconspath ], BUNDLEDIR = sconspath, SENFDIR = sconspath, + SENFINCDIR = sconspath, SENFSYSLAYOUT = False) try: env.MergeFlags(file(os.path.join(path,"senf.conf")).read()) @@ -150,6 +214,7 @@ def SetupForSENF(env, senf_path = []): print "\nUsing system SENF in '%s/'\n" % sconspath env.Append(BUNDLEDIR = os.path.join(sconspath,"lib/senf"), SENFDIR = sconspath, + SENFINCDIR = '%s/include' % sconspath, SENFSYSLAYOUT = True) break else: @@ -160,7 +225,7 @@ def SetupForSENF(env, senf_path = []): # Only add senf after all configure checks have run env.Append( - CPPPATH = '${NEED_BOOST_EXT and "$SENFDIR/boost_ext" or None}', + CPPPATH = '${NEED_BOOST_EXT and "$SENFINCDIR/boost_ext" or None}', LIBS = [ 'senf', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ], ) @@ -195,15 +260,86 @@ def Glob(env, exclude=[], subdirs=[]): return (sources, testSources) -def Configure(env): - conf = env.Configure(clean=False, help=False, custom_tests = senfconf.Tests()) - env.Replace( - BOOST_VERSION = conf.CheckBoostVersion(), - BOOST_VARIANT = conf.CheckBoostVariants( '', 'mt' ), - NEED_BOOST_EXT = not conf.CheckCXXHeader("boost/bimap.hpp"), - ) - conf.Finish() +@senfconf.Test +def CheckSTLCopyN(context): + context.Message("Checking for 'copy_n' implementation... ") + versions = [ ('', 'std::copy_n', 'STD'), + ('', '__gnu_cxx::copy_n', 'GNUCXX') ] + for include, name, define in versions: + ret = context.TryCompile("#include %s\n" + "int main(int,char**) { int *a,*b; %s(a,0,b); }\n" + % (include, name), + ".cc") + if ret: + context.Result(name) + context.sconf.Define("HAVE_%s_COPYN" % define, + 1, + "Define one of " + + ", ".join(("HAVE_%s_COPYN" % elt[2] for elt in versions))) + return ret + + context.Result(False) + return False + + +@senfconf.Test +def CheckTempBufferStrategy(context): + context.Message("Checking for optimal temporary buffer strategy... ") + + def check(): + # locals + ret = context.TryCompile("void test(int n){int a[n];}",".cc") + if ret: return "locals" + + # alloca + ret = context.TryCompile("#include \n" + "void test(int a){void *b(alloca(a));}" + ".cc") + if ret: return "alloca" + + # fallback: new + return "new" + + ret = check() + context.Result(ret) + context.sconf.Define("SENF_BUFFER_USE_%s" % ret.upper(), + 1, + "Define one of SENF_BUFFER_USE_LOCALS, SENF_BUFFER_USE_ALLOCA, " + "SENF_BUFFER_USE_NEW") + return ret + + +def Fail(msg): + SCons.Util.display("scons: *** %s" % msg) + Exit(1) + + +def Configure(env, customChecks=None): + conf = env.Configure(clean=False, + help=False, + custom_tests=senfconf.Tests(), + config_h="#/senf/autoconf.hh") + + # Boost + if not conf.CheckBoostVersion(): + Fail("Boost includes not found") + if not conf.env['ARGUMENT_VARIABLES'].has_key('BOOST_VARIANT'): conf.CheckBoostVariants( '', 'mt' ) + conf.env.Replace(NEED_BOOST_EXT = not conf.CheckCXXHeader("boost/bimap.hpp")) + conf.CheckCXXHeader("boost/spirit/include/classic.hpp") + + # Compiler support + conf.CheckTempBufferStrategy() + + # Standard library stuff + if not conf.CheckSTLCopyN(): + Fail("No 'copy_n' implementation found") + conf.CheckFunc("timerfd_create") + # User checks + if customChecks: + customChecks(conf) + + conf.Finish() tagfiles = None