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
15 senfutil.loadTools(env)
18 Additional top-level build targets:
20 prepare Create all target files not part of the repository
21 default Build all default targets (like calling scons with no arguments)
22 examples Build all examples
23 all_tests Build and run unit tests for all modules
24 test_changes Build tests only for files with local changes (queries svn or git)
25 all_docs Build documentation for all modules
27 install_all Install SENF into $$PREFIX
28 deb Build debian source and binary package
29 debsrc Build debian source package
30 debbin Build debian binary package
31 linklint Check links of doxygen documentation with 'linklint'
32 fixlinks Fix broken links in doxygen documentation
33 all_valgrinds Run all tests under valgrind/memcheck
34 lcov Generate test coverage output in doc/lcov and lcov.info
36 The following additional targets may be called within subdirectories, either
37 using '$ scons -u <target>' or '$ scons <directory>/<target>:
39 test Build and run unit test for this module
40 doc Build the documentation of this module
41 valgrind Run the unit test of this module under valgrind
43 When cleaning up using '$ scons -c <target>', some targets are handled specially:
45 all Remove everything generated by the build including temporary and
48 some Remove all files not needed for building like temporary or backup
49 files. This target is only valid when called as clean target.
51 You may execute targets on a remote host via ssh (if the directory layout is the
54 $ scons <target>@[<user>@]<host>
56 Some more elaborate unit tests may be enabled by setting appropritate variables
57 in the shell (unix) environment
59 SENF_TIMING_CRITICAL_TESTS
60 Enables unit tests which depend on timing measurements. These
61 unit tests should only be run on a single core and an otherwise
64 SENF_WLAN_TEST_INTERFACE
65 WLAN interface to use for testing. The interface should not be
68 SENF_ETH_TEST_INTERFACE
69 Ethernet interface to use for testing. The interface should not
72 Some unit tests will only run when executed to 'root'.
76 expandLogOption = senfutil.expandLogOption,
77 CXXFLAGS_ = env.BuildTypeOptions('CXXFLAGS'),
78 CPPDEFINES_ = env.BuildTypeOptions('CPPDEFINES'),
79 LINKFLAGS_ = env.BuildTypeOptions('LINKFLAGS'),
82 IMPORT_ENV = [ 'PATH', 'HOME', 'SSH_*', 'SENF*', 'CCACHE_*', 'DISTCC_*' ],
84 CLEAN_SOME_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache' ],
85 CLEAN_PATTERNS = [ '.sconsign*', '.sconf_temp' ],
87 CPPPATH = [ '#', '$BUILDDIR',
88 '${NEED_BOOST_EXT and "#/boost_ext" or None}' ],
89 LIBPATH = [ '$LOCALLIBDIR' ],
90 LIBS = [ '$EXTRA_LIBS' ],
91 EXTRA_LIBS = [ 'rt' ],
92 TEST_EXTRA_LIBS = [ ],
93 VALGRINDARGS = [ '--num-callers=50' ],
95 CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
96 CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
98 # INLINE_OPTS_DEBUG are insane. Only useful for inline debugging. Need at least 1G free RAM
99 INLINE_OPTS_DEBUG = [ '-finline-limit=20000', '-fvisibility-inlines-hidden',
100 '-fno-inline-functions', '-Winline'
101 '--param','large-function-growth=10000',
102 '--param', 'large-function-insns=10000',
103 '--param','inline-unit-growth=10000' ],
104 INLINE_OPTS_NORMAL = [ '-finline-limit=5000', '--param', 'inline-unit-growth=60' ],
105 INLINE_OPTS = [ '$INLINE_OPTS_NORMAL' ],
106 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
107 '-pipe', '$CXXFLAGS_', '-fno-strict-aliasing' ],
108 CXXFLAGS_final = [ '-O3' ],
109 CXXFLAGS_normal = [ '-O2', '-g' ],
110 CXXFLAGS_debug = [ '-O0', '-g' ],
112 CPPDEFINES = [ '$expandLogOption', '$CPPDEFINES_' ],
113 CPPDEFINES_final = [ 'SENF_PPI_NOTRACE', 'BOOST_NO_MT', 'NDEBUG', 'BOOST_DISABLE_ASSERTS' ],
114 CPPDEFINES_normal = [ 'SENF_DEBUG' ],
115 CPPDEFINES_debug = [ '$CPPDEFINES_normal' ],
117 LINKFLAGS = [ '-rdynamic', '$LINKFLAGS_' ],
118 LINKFLAGS_final = [ ],
119 LINKFLAGS_normal = [ '-Wl,-S' ],
120 LINKFLAGS_debug = [ '-g' ],
124 LIBINSTALLDIR = '$PREFIX${syslayout and "/lib" or ""}',
125 BININSTALLDIR = '$PREFIX${syslayout and "/bin" or ""}',
126 INCLUDEINSTALLDIR = '$PREFIX${syslayout and "/include" or ""}',
127 CONFINSTALLDIR = '${syslayout and "$LIBINSTALLDIR/senf" or "$PREFIX"}',
128 OBJINSTALLDIR = '$CONFINSTALLDIR',
129 DOCINSTALLDIR = '$PREFIX${syslayout and "/share/doc/senf" or "/manual"}',
130 SCONSINSTALLDIR = '$CONFINSTALLDIR/site_scons',
132 BUILDDIR = '${FLAVOR and "#/build/$FLAVOR" or "#"}',
133 LOCALLIBDIR = '$BUILDDIR',
138 VALGRIND = "valgrind",
139 SCONSBIN = env.File("#/tools/scons"),
140 SCONSARGS = ([ '-Q', '-j$CONCURRENCY_LEVEL' ] +
141 [ '%s=%s' % (k,v) for k,v in ARGLIST ]),
142 SCONS = "@$SCONSBIN $SCONSARGS",
143 CONCURRENCY_LEVEL = env.GetOption('num_jobs') or 1,
144 TOPDIR = env.Dir('#').abspath,
145 LIBADDSUFFIX = '${FLAVOR and "_$FLAVOR" or ""}',
146 OBJADDSUFFIX = '${LIBADDSUFFIX}',
150 # Set variables from command line
151 senfutil.parseArguments(
153 BoolVariable('final', 'Build final (optimized) build', False),
154 BoolVariable('debug', 'Link in debug symbols', False),
155 BoolVariable('profile', 'compile and link with the profiling enabled option', False),
156 BoolVariable('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
157 BoolVariable('sparse_tests', 'Link tests against object files and not the senf lib', False)
163 LINKFLAGS = [ '-pg' ],
164 CXXFLAGS = [ '-pg' ],
168 # Add UNIX env vars matching IMPORT_ENV patterns into the execution environment
169 senfutil.importProcessEnv(env)
171 # Handle 'test_changes'
172 if 'test_changes' in COMMAND_LINE_TARGETS and not env.has_key('only_tests'):
173 import SparseTestHack
174 env['only_tests'] = " ".join(x.abspath for x in SparseTestHack.findSCMChanges(env))
176 if env.has_key('only_tests') : env['sparse_tests'] = True
180 ###########################################################################
183 SConscript('SConfigure')
185 # Only add this here, after all configure checks have run
187 env.Append(LIBS = '$LIBSENF$LIBADDSUFFIX',
188 EXTRA_LIBS = [ '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
191 ###########################################################################
193 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
194 # Create it even when cleaning, to silence the doxygen builder warnings
195 if not os.path.exists("doclib/Doxyfile.local"):
196 Execute(Touch("doclib/Doxyfile.local"))
198 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
199 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
200 env.Execute([ "$SCONS prepare" ])
205 SConscript("debian/SConscript")
207 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
208 if env['sparse_tests']:
209 import SparseTestHack
210 SparseTestHack.setup(env)
211 if env.subst('$BUILDDIR') == '#':
212 SConscript("SConscript")
214 SConscript("SConscript", variant_dir=env.subst('$BUILDDIR'), src_dir='#', duplicate=False)
215 SConscript("Examples/SConscript")
216 SConscript("HowTos/SConscript")
217 SConscript("doclib/SConscript")
218 if env['sparse_tests']:
219 verbose = 'test_changes' in COMMAND_LINE_TARGETS
220 SparseTestHack.build(env, verbose, verbose)
222 ###########################################################################
223 # Define build targets
225 #### install_all, default, all_tests, all
226 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
227 'site_scons/senfutil.py',
228 'site_scons/yaptu.py' ])
229 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
230 FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
231 env.Install('${INCLUDEINSTALLDIR}', 'boost_ext')
232 env.Install('${INCLUDEINSTALLDIR}/senf', 'senf/boost_intrusive')
234 env.Alias('install_all', env.FindInstalledFiles())
235 env.Alias('default', DEFAULT_TARGETS)
236 env.Alias('all_tests', env.FindAllBoostUnitTests())
237 env.Alias('test_changes', 'all_tests')
238 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
240 #### prepare and -c some
241 env.PhonyTarget('prepare', [], [])
242 env.PhonyTarget('some', [], [])
245 env.Alias('all_valgrinds')
246 if env.get('HAVE_VALGRIND'):
247 for test in env.FindAllBoostUnitTests():
248 stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'),
249 [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
250 [ """$VALGRIND --tool=memcheck
252 --suppressions=${SOURCES[1]}
254 ${SOURCES[0]} --result_code=no $BOOSTTESTARGS
255 """.replace("\n"," "),
257 alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
258 env.Alias('all_valgrinds', alias)
261 env.PhonyTarget('lcov', [], [
264 ' BUILDDIR="#/build/lcov"'
265 ' CCFLAGS+="-fprofile-arcs -ftest-coverage"'
270 ' --directory $TOPDIR/build/lcov/senf'
272 ' --output-file /tmp/senf_lcov.info'
273 ' --base-directory $TOPDIR',
275 ' --output-file lcov.info'
276 ' --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*"',
278 ' --output-directory doc/lcov'
279 ' --title all_tests lcov.info',
280 'rm /tmp/senf_lcov.info' ])
281 senfutil.CleanGlob(env, ['lcov','some','all'], [ '*.gcno', '*.gcda', '*.gcov' ])
282 env.Clean(['lcov', 'all'], [ 'lcov.info', env.Dir('doc/lcov'), env.Dir('build/lcov') ])
286 env.Clean('all', ('.prepare-stamp', env.Dir('dist'), env.Dir('build')))
288 senfutil.CleanGlob(env, 'all', '$CLEAN_PATTERNS')
289 senfutil.CleanGlob(env, ['some', 'all'], '$CLEAN_SOME_PATTERNS')
291 if env.GetOption('clean') and 'all' in BUILD_TARGETS:
292 env.Depends('all', ('lcov', 'all_valgrinds'))
293 # Disable writing to the deleted .sconsign file
294 import SCons.SConsign
295 SCons.SConsign.write = lambda : None
297 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
298 Execute(Touch(".prepare-stamp"))
300 ### execute targets on remote hosts
301 for target in COMMAND_LINE_TARGETS:
303 realtarget, host = target.split('@',1)
304 cwd=env.GetLaunchDir()
305 home=os.environ['HOME']+'/'
306 if cwd.startswith(home) : cwd = cwd[len(home):]
307 args = [ '$SCONSARGS' ]
308 if env.GetLaunchDir() != os.getcwd():
310 env.PhonyTarget(target, [], [ "ssh $HOST scons $SCONSARGS -C $DIR $RTARGET" ],
311 HOST=host, RTARGET=realtarget, DIR=cwd, SCONSARGS=args)
313 env.PhonyTarget('clean', [], [
314 lambda **args: sys.stderr.write(
315 "=================================================================\n"
316 "'clean' is not a valid target, use the '-c' option instead:\n"
318 "=================================================================\n") ])