Add broken doxygen namesoace handling workaround
[senf.git] / senfscons / SENFSCons.py
1 import os.path, SCons.Options, SCons.Environment, SCons.Script.SConscript, glob
2
3 SCONS_TOOLS = [
4     "Doxygen",
5     "Dia2Png",
6 ]
7
8 opts = None
9 finalizers = []
10
11 basedir = os.path.split(__file__)[0]
12
13 def InitOpts():
14     global opts
15     if opts is not None: return
16     opts = SCons.Options.Options('SConfig')
17     opts.Add('CXX', 'C++ compiler to use', 'g++')
18     opts.Add('EXTRA_DEFINES', 'Additional preprocessor defines', '')
19     opts.Add('EXTRA_LIBS', 'Additional libraries to link against', '')
20     opts.Add(SCons.Options.BoolOption('final','Enable optimization',0))
21
22 def Finalizer(f):
23     global finalizers
24     finalizers.append(f)
25
26 def UseBoost():
27     global opts
28     InitOpts()
29     opts.Add('BOOST_INCLUDES', 'Boost include directory', '')
30     opts.Add('BOOST_VARIANT', 'The boost variant to use', '')
31     opts.Add('BOOST_TOOLSET', 'The boost toolset to use', '')
32     opts.Add('BOOST_RUNTIME', 'The boost runtime to use', '')
33     opts.Add('BOOST_DEBUG_RUNTIME', 'The boost debug runtime to use', '')
34     opts.Add('BOOST_LIBDIR', 'The directory of the boost libraries', '')
35     Finalizer(FinalizeBoost)
36
37 def FinalizeBoost(env):
38     env.Tool('BoostUnitTests', [basedir])
39
40     if env['BOOST_TOOLSET']:
41         runtime = ""
42         if env['final'] : runtime += env.get('BOOST_RUNTIME','')
43         else            : runtime += env.get('BOOST_DEBUG_RUNTIME','gd')
44         if env['STLPORT_LIB'] : runtime += "p"
45         if runtime: runtime = "-" + runtime
46         env['BOOST_VARIANT'] = "-" + env['BOOST_TOOLSET'] + runtime
47
48     env['BOOSTTESTLIB'] = 'libboost_unit_test_framework' + env['BOOST_VARIANT']
49
50     env.Append(LIBPATH = [ '$BOOST_LIBDIR' ],
51                CPPPATH = [ '$BOOST_INCLUDES' ])
52
53 def UseSTLPort():
54     global opts
55     InitOpts()
56     opts.Add('STLPORT_INCLUDES', 'STLport include directory', '')
57     opts.Add('STLPORT_LIB', 'Name of the stlport library or empty to not use stlport', '')
58     opts.Add('STLPORT_DEBUGLIB', 'Name of the stlport debug library','')
59     opts.Add('STLPORT_LIBDIR', 'The directory of the stlport libraries','')
60     Finalizer(FinalizeSTLPort)
61
62 def FinalizeSTLPort(env):
63     if env['STLPORT_LIB']:
64         if not env['STLPORT_DEBUGLIB']:
65             env['STLPORT_DEBUGLIB'] = env['STLPORT_LIB'] + '_stldebug'
66         env.Append(LIBPATH = [ '$STLPORT_LIBDIR' ],
67                    CPPPATH = [ '$STLPORT_INCLUDES' ])
68         if env['final']:
69             env.Append(LIBS = [ '$STLPORT_LIB' ])
70         else:
71             env.Append(LIBS = [ '$STLPORT_DEBUGLIB' ],
72                        CPPDEFINES = [ '_STLP_DEBUG' ])
73
74 def MakeEnvironment():
75     global opts, finalizers
76     InitOpts()
77     env = SCons.Environment.Environment(options=opts)
78     if SCons.Script.SConscript.Arguments.get('final'):
79         env['final'] = 1
80     env.Help(opts.GenerateHelpText(env))
81     #conf = env.Configure()
82     #env = conf.env
83     if os.environ.has_key('SSH_AUTH_SOCK'):
84         env.Append( ENV = { 'SSH_AUTH_SOCK': os.environ['SSH_AUTH_SOCK'] } )
85
86     for finalizer in finalizers:
87         finalizer(env)
88
89     for tool in SCONS_TOOLS:
90         env.Tool(tool, [basedir])
91
92     env.Append(CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ],
93                LOCALLIBDIR = [ '#' ],
94                LIBPATH = [ '$LOCALLIBDIR' ])
95
96     if env['final']:
97         env.Append(CXXFLAGS = [ '-O3' ],
98                    CPPDEFINES = [ 'NDEBUG' ])
99     else:
100         env.Append(CXXFLAGS = [ '-O0', '-g', '-fno-inline' ],
101                    LINKFLAGS = [ '-g' ])
102
103     env.Append(CPPDEFINES = [ '$EXTRA_DEFINES' ],
104                LIBS = [ '$EXTRA_LIBS' ])
105
106     #return conf.Finish()
107     return env
108
109 def GlobSources(exclude=[]):
110     testSources = glob.glob("*.test.cc")
111     sources = [ x for x in glob.glob("*.cc") if x not in testSources and x not in exclude ]
112     return (sources, testSources)
113     
114 def StandardTargets(env):
115     all = env.Alias('all')
116     env.Clean(all, [ '.sconsign', '.sconf_temp', 'config.log', 'ChangeLog.bak', '.clean'
117                      ] + glob.glob("*~"))
118     env.Depends(all, '.')
119
120 def GlobalTargets(env):
121     command = "find -name .svn -prune -o \( -name '*.hh' -o -name '*.ih' -o -name '*.cc' -o -name '*.cci' -o -name '*.ct' -o -name '*.cti' -o -name '*.mpp' \) -print " \
122               "| xargs -r awk -F '//' '/%s/{print ARGV[ARGIND] \":\" FNR \":\" $2}' > $TARGET"
123     env.AlwaysBuild(env.Command('TODOS',None,[ command % 'TODO' ]))
124     env.AlwaysBuild(env.Command('FIXMES',None,[ command % ' FIXME' ]))
125     env.AlwaysBuild(env.Command('BUGS',None,[ command % 'BUG' ] ))
126     env.Alias('status',[ 'TODOS', 'FIXMES', 'BUGS' ])
127
128 def LibPath(lib): return '$LOCALLIBDIR/lib%s.a' % lib
129     
130 def Objects(env, sources, testSources = None, LIBS = []):
131     if type(sources) == type(()):
132         testSources = sources[1]
133         sources = sources[0]
134
135     objects = None
136     if sources:
137         objects = env.Object(sources)
138
139     if testSources:
140         test = env.BoostUnitTests(
141             target = 'test',
142             source = sources,
143             test_source = testSources,
144             LIBS = LIBS,
145             DEPENDS = [ env.File(LibPath(x)) for x in LIBS ])
146         env.Alias('all_tests', test)
147         # Hmm ... here I'd like to use an Alias instead of a file
148         # however the alias does not seem to live in the subdirectory
149         # which breaks 'scons -u test'
150         env.Alias(env.File('test'), test)
151
152     return objects
153
154 def DoxyGlob(exclude=[]):
155     sources = [ f
156                 for ext in ("cci", "ct", "cti", "h", "hh", "ih", "mmc", "dox")
157                 for f in glob.glob("*."+ext)
158                 if f not in exclude ]
159     return sources
160
161 def Doxygen(env, doxyfile="Doxyfile", extra_sources = []):
162     docs = env.Doxygen(doxyfile)
163     # The last target is the (optional) tagfile
164     if os.path.basename(str(docs[-1])) != '.stamp':
165         # Postprocess the tag file to remove the (broken) namespace
166         # references
167         env.AddPostAction(
168             docs,
169             env.Action([ "xsltproc -o ${TARGETS[-1]}.temp %s ${TARGETS[-1]}"
170                          % os.path.join(basedir,"tagmunge.xsl"),
171                          "mv ${TARGETS[-1]}.temp ${TARGETS[-1]}" ]))
172         env.Clean(docs[-1],"$TARGET.temp")
173     env.Depends(docs,extra_sources)
174     env.Alias('all_docs', *docs)
175     return docs
176
177 def Lib(env, library, sources, testSources = None, LIBS = []):
178     objects = Objects(env,sources,testSources,LIBS=LIBS)
179     lib = None
180     if objects:
181         lib = env.Library(env.File(LibPath(library)),objects)
182         env.Default(lib)
183         env.Append(ALLLIBS = library)
184     return lib
185
186 def Binary(env, binary, sources, testSources = None, LIBS = []):
187     objects = Objects(env,sources,testSources,LIBS=LIBS)
188     program = None
189     if objects:
190         progEnv = env.Copy()
191         progEnv.Prepend(LIBS = LIBS)
192         program = progEnv.Program(target=binary,source=objects)
193         env.Default(program)
194         env.Depends(program, [ env.File(LibPath(x)) for x in LIBS ])
195     return program