25e124915fd04afffd5e7bb6cbfc257f207e5798
[senf.git] / site_scons / senfutil.py
1 import os.path
2 from SCons.Script import *
3
4 def parseLogOption(value):
5     stream, area, level = ( x.strip() for x in value.strip().split('|') )
6     stream = ''.join('(%s)' % x for x in stream.split('::') )
7     if area : area = ''.join( '(%s)' % x for x in area.split('::') )
8     else    : area = '(_)'
9     return '((%s,%s,%s))' % (stream,area,level)
10
11 def expandLogOption(target, source, env, for_signature):
12     if env.get('LOGLEVELS'):
13         return [ 'SENF_LOG_CONF="' + ''.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )+'"']
14     else:
15         return []
16
17 class BuildTypeOptions:
18     def __init__(self, var):
19         self._var = var
20
21     def __call__(self, target, source, env, for_signature):
22         type = env['final'] and "final" or env['debug'] and "debug" or "normal"
23         return env[self._var + "_" + type]
24
25 def parseArguments(env, *defs):
26     vars = Variables(args=ARGUMENTS)
27     vars.AddVariables(*defs)
28     vars.Update(env)
29     env.Help("""
30 Any construction environment variable may be set from the scons
31 command line (see SConstruct file and SCons documentation for a list
32 of variables) using
33
34    VARNAME=value    Assign new value  
35    VARNAME+=value   Append value at end
36
37 Special command line parameters:
38 """)
39     env.Help(vars.GenerateHelpText(env))
40     for k,v in vars.UnknownVariables().iteritems():
41         if k.endswith('+'):
42             env.Append(**{k[:-1]: v})
43         else:
44             env.Replace(**{k: v})
45
46
47 ###########################################################################
48 # This looks much more complicated than it is: We do three things here:
49 # a) switch between final or debug options
50 # b) parse the LOGLEVELS parameter into the correct SENF_LOG_CONF syntax
51 # c) check for a local SENF, set options accordingly and update that SENF if needed
52
53 def SetupForSENF(env, senf_paths = []):
54     senf_paths.extend(('senf', '../senf', os.path.dirname(os.path.dirname(__file__)),
55                        '/usr/local', '/usr'))
56     env.Append(
57         LIBS              = [ 'senf', 'rt', '$BOOSTREGEXLIB',
58                               '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
59                               '$BOOSTFSLIB' ],
60         BOOSTREGEXLIB     = 'boost_regex',
61         BOOSTIOSTREAMSLIB = 'boost_iostreams',
62         BOOSTSIGNALSLIB   = 'boost_signals',
63         BOOSTFSLIB        = 'boost_filesystem',
64         
65         CXXFLAGS          = [ '-Wno-long-long', '$CXXFLAGS_' ],
66         CXXFLAGS_         = BuildTypeOptions('CXXFLAGS'),
67         
68         CPPDEFINES        = [ '$expandLogOption', '$CPPDEFINES_' ],
69         expandLogOption   = expandLogOption,
70         CPPDEFINES_       = BuildTypeOptions('CPPDEFINES'),
71         
72         LINKFLAGS         = [ '-rdynamic', '$LINKFLAGS_' ],
73         LINKFLAGS_        = BuildTypeOptions('LINKFLAGS'),
74
75         LOGLEVELS         = [ '$LOGLEVELS_' ],
76         LOGLEVELS_        = BuildTypeOptions('LOGLEVELS'),
77         )
78
79     env.SetDefault( 
80         CXXFLAGS_final    = [],
81         CXXFLAGS_normal   = [],
82         CXXFLAGS_debug    = [],
83
84         CPPDEFINES_final  = [],
85         CPPDEFINES_normal = [],
86         CPPDEFINES_debug  = [],
87
88         LINKFLAGS_final   = [],
89         LINKFLAGS_normal  = [],
90         LINKFLAGS_debug   = [],
91
92         LOGLEVELS_final   = [],
93         LOGLEVELS_normal  = [],
94         LOGLEVELS_debug   = [],
95         )
96
97     # Interpret command line options
98     parseArguments(
99         env, 
100         BoolVariable('final', 'Build final (optimized) build', False),
101         BoolVariable('debug', 'Link in debug symbols', False),
102     )
103
104     # If we have a symbolic link (or directory) 'senf', we use it as our
105     # senf repository
106     for path in senf_paths:
107         if not path.startswith('/') : sconspath = '#/%s' % path
108         else                        : sconspath = path
109         if os.path.exists(os.path.join(path,"senf/config.hh")):
110             print "\nUsing SENF in '%s'\n" \
111                 % ('/..' in sconspath and os.path.abspath(path) or sconspath)
112             env.Append( LIBPATH = [ sconspath ],
113                         CPPPATH = [ sconspath ],
114                         BUNDLEDIR = sconspath )
115             try:
116                 env.MergeFlags(file(os.path.join(path,"senf.conf")).read())
117             except IOError:
118                 print "(SENF configuration file 'senf.conf' not found, assuming non-final SENF)"
119                 env.Append(CPPDEFINES = [ 'SENF_DEBUG' ])
120             break
121         elif os.path.exists(os.path.join(path,"include/senf/config.hh")):
122             print "\nUsing system SENF in '%s/'\n" % sconspath
123             env.Append(BUNDLEDIR = os.path.join(sconspath,"lib/senf"))
124             break
125     else:
126         print "\nSENF library not found .. trying build anyway !!\n"
127
128
129 def DefaultOptions(env):
130     env.Append(
131         CXXFLAGS         = [ '-Wall', '-Woverloaded-virtual' ],
132         CXXFLAGS_final   = [ '-O2' ],
133         CXXFLAGS_normal  = [ '-O0', '-g' ],
134         CXXFLAGS_debug   = [ '$CXXFLAGS_normal' ],
135
136         LINKFLAGS_normal = [ '-Wl,-S' ],
137         LINKFLAGS_debug  = [ '-g' ],
138     )