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