3 import sys, glob, os.path, fnmatch
4 import SENFSCons, senfutil
6 ###########################################################################
7 # Load utilities and setup libraries and configure build
11 env.Decider('MD5-timestamp')
12 env.EnsureSConsVersion(1,2)
14 # Load all the local SCons tools
18 env.Tool('InstallSubdir')
21 env.Tool('CombinedObject')
22 env.Tool('PhonyTarget')
23 env.Tool('InstallDir')
26 Additional top-level build targets:
28 prepare Create all target files not part of the repository
29 default Build all default targets (like calling scons with no arguments)
30 examples Build all examples
31 all_tests Build and run unit tests for all modules
32 all_docs Build documentation for all modules
34 install_all Install SENF into $$PREFIX
35 deb Build debian source and binary package
36 debsrc Build debian source package
37 debbin Build debian binary package
38 linklint Check links of doxygen documentation with 'linklint'
39 fixlinks Fix broken links in doxygen documentation
40 all_valgrinds Run all tests under valgrind/memcheck
41 lcov Generate test coverage output in doc/lcov and lcov.info
45 ENV = { 'PATH' : os.environ.get('PATH'), 'HOME' : os.environ.get('HOME') },
46 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
50 LIBPATH = [ '$LOCALLIBDIR' ],
51 LIBS = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB',
52 '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ],
53 TEST_EXTRA_LIBS = [ ],
54 VALGRINDARGS = [ '--num-callers=50' ],
57 LIBINSTALLDIR = '$PREFIX${syslayout and "/lib" or ""}',
58 BININSTALLDIR = '$PREFIX${syslayout and "/bin" or ""}',
59 INCLUDEINSTALLDIR = '$PREFIX${syslayout and "/include" or ""}',
60 CONFINSTALLDIR = '${syslayout and "$LIBINSTALLDIR/senf" or "$PREFIX"}',
61 OBJINSTALLDIR = '$CONFINSTALLDIR',
62 DOCINSTALLDIR = '$PREFIX${syslayout and "/share/doc/senf" or "/manual"}',
63 SCONSINSTALLDIR = '$CONFINSTALLDIR/site_scons',
65 CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
66 CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
68 # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
69 INLINE_OPTS_DEBUG = [ '-finline-limit=20000', '-fvisibility-inlines-hidden',
70 '-fno-inline-functions', '-Winline'
71 '--param','large-function-growth=10000',
72 '--param', 'large-function-insns=10000',
73 '--param','inline-unit-growth=10000' ],
74 INLINE_OPTS_NORMAL = [ '-finline-limit=5000' ],
75 INLINE_OPTS = [ '$INLINE_OPTS_NORMAL' ],
76 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
78 CXXFLAGS_ = senfutil.BuildTypeOptions('CXXFLAGS'),
79 CXXFLAGS_final = [ '-O3' ],
80 CXXFLAGS_normal = [ '-O0', '-g' ],
81 CXXFLAGS_debug = [ '$CXXFLAGS_normal' ],
83 CPPDEFINES = [ '$expandLogOption', '$CPPDEFINES_' ],
84 expandLogOption = senfutil.expandLogOption,
85 CPPDEFINES_ = senfutil.BuildTypeOptions('CPPDEFINES'),
86 CPPDEFINES_final = [ ],
87 CPPDEFINES_normal = [ 'SENF_DEBUG' ],
88 CPPDEFINES_debug = [ '$CPPDEFINES_normal' ],
90 LINKFLAGS = [ '-rdynamic', '$LINKFLAGS_' ],
91 LINKFLAGS_ = senfutil.BuildTypeOptions('LINKFLAGS'),
92 LINKFLAGS_final = [ ],
93 LINKFLAGS_normal = [ '-Wl,-S' ],
94 LINKFLAGS_debug = [ '-g' ],
101 SCONSBIN = env.File("#/tools/scons"),
102 SCONS = "@$SCONSBIN -Q -j$CONCURRENCY_LEVEL",
103 CONCURRENCY_LEVEL = env.GetOption('num_jobs') or 1,
104 TOPDIR = env.Dir('#').abspath,
107 # Set variables from command line
108 senfutil.parseArguments(
110 BoolVariable('final', 'Build final (optimized) build', False),
111 BoolVariable('debug', 'Link in debug symbols', False),
112 BoolVariable('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
117 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
118 # Create it even when cleaning, to silence the doxygen builder warnings
119 if not os.path.exists("doclib/Doxyfile.local"):
120 Execute(Touch("doclib/Doxyfile.local"))
122 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
123 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
124 env.Execute([ "$(SCONS) prepare" ])
129 SConscript("debian/SConscript")
131 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
132 SConscript("senf/SConscript")
133 SConscript("Examples/SConscript")
134 SConscript("HowTos/SConscript")
135 SConscript("doclib/SConscript")
137 ###########################################################################
138 # Define build targets
141 libsenf = env.Library("$LOCALLIBDIR/${LIBSENF}${LIBADDSUFFIX}", env['ALLOBJECTS'])
143 env.Install('$LIBINSTALLDIR', libsenf)
145 def create(target, source, env):
146 file(str(target[0]), 'w').write(source[0].get_contents()+"\n")
147 env['BUILDERS']['CreateFile'] = Builder(action = create)
149 conf = env.CreateFile("${LOCALLIBDIR}/${LIBSENF}${LIBADDSUFFIX}.conf",
150 env.Value(env.subst("$_CPPDEFFLAGS")))
152 env.Install('$CONFINSTALLDIR', conf)
154 #### install_all, default, all_tests, all
155 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
156 'site_scons/senfutil.py',
157 'site_scons/yaptu.py' ])
158 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
159 FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
160 env.Install('${INCLUDEINSTALLDIR}', 'boost')
162 env.Alias('install_all', env.FindInstalledFiles())
163 env.Alias('default', DEFAULT_TARGETS)
164 env.Alias('all_tests', env.FindAllBoostUnitTests())
165 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
168 env.PhonyTarget('prepare', [], [])
171 for test in env.FindAllBoostUnitTests():
172 stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'),
173 [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
174 [ """valgrind --tool=memcheck
176 --suppressions=${SOURCES[1]}
178 ${SOURCES[0]} $BOOSTTESTARGS;
179 [ $$? -ne 99 ] || exit 1""".replace("\n"," "),
181 alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
182 env.Alias('all_valgrinds', alias)
185 env.PhonyTarget('lcov', [], [
186 '$SCONS debug=1 CCFLAGS+="-fprofile-arcs -ftest-coverage" LIBS+="gcov" all_tests',
187 '$LCOV --follow --directory $TOPDIR/senf --capture --output-file /tmp/senf_lcov.info --base-directory $TOPDIR',
188 '$LCOV --output-file lcov.info --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*" ',
189 '$GENHTML --output-directory doc/lcov --title all_tests lcov.info',
190 'rm /tmp/senf_lcov.info' ])
191 if env.GetOption('clean'):
192 env.Depends('lcov', 'all_tests')
193 env.Clean('lcov', [ os.path.join(path,f)
194 for path, subdirs, files in os.walk('.')
195 for pattern in ('*.gcno', '*.gcda', '*.gcov')
196 for f in fnmatch.filter(files,pattern) ] +
197 [ 'lcov.info', env.Dir('doc/lcov') ])
200 env.Clean('all', ('.prepare-stamp', env.Dir('dist')))
201 if env.GetOption('clean') : env.Depends('all', ('lcov', 'all_valgrinds'))
203 if env.GetOption('clean'):
204 env.Clean('all', [ os.path.join(path,f)
205 for path, subdirs, files in os.walk('.')
206 for pattern in env['CLEAN_PATTERNS']
207 for f in fnmatch.filter(files,pattern) ])
209 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
210 Execute(Touch(".prepare-stamp"))