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' ],
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('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
156 BoolVariable('sparse_tests', 'Link tests against object files and not the senf lib', False)
159 # Add UNIX env vars matching IMPORT_ENV patterns into the execution environment
160 senfutil.importProcessEnv(env)
162 # Handle 'test_changes'
163 if 'test_changes' in COMMAND_LINE_TARGETS and not env.has_key('only_tests'):
164 import SparseTestHack
165 env['only_tests'] = " ".join(x.abspath for x in SparseTestHack.findSCMChanges(env))
167 if env.has_key('only_tests') : env['sparse_tests'] = True
171 ###########################################################################
174 SConscript('SConfigure')
176 # Only add this here, after all configure checks have run
178 env.Append(LIBS = '$LIBSENF$LIBADDSUFFIX',
179 EXTRA_LIBS = [ '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
182 ###########################################################################
184 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
185 # Create it even when cleaning, to silence the doxygen builder warnings
186 if not os.path.exists("doclib/Doxyfile.local"):
187 Execute(Touch("doclib/Doxyfile.local"))
189 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
190 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
191 env.Execute([ "$SCONS prepare" ])
196 SConscript("debian/SConscript")
198 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
199 if env['sparse_tests']:
200 import SparseTestHack
201 SparseTestHack.setup(env)
202 if env.subst('$BUILDDIR') == '#':
203 SConscript("SConscript")
205 SConscript("SConscript", variant_dir=env.subst('$BUILDDIR'), src_dir='#', duplicate=False)
206 SConscript("Examples/SConscript")
207 SConscript("HowTos/SConscript")
208 SConscript("doclib/SConscript")
209 if env['sparse_tests']:
210 verbose = 'test_changes' in COMMAND_LINE_TARGETS
211 SparseTestHack.build(env, verbose, verbose)
213 ###########################################################################
214 # Define build targets
216 #### install_all, default, all_tests, all
217 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
218 'site_scons/senfutil.py',
219 'site_scons/yaptu.py' ])
220 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
221 FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
222 env.Install('${INCLUDEINSTALLDIR}', 'boost_ext')
223 env.Install('${INCLUDEINSTALLDIR}/senf', 'senf/boost_intrusive')
225 env.Alias('install_all', env.FindInstalledFiles())
226 env.Alias('default', DEFAULT_TARGETS)
227 env.Alias('all_tests', env.FindAllBoostUnitTests())
228 env.Alias('test_changes', 'all_tests')
229 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
231 #### prepare and -c some
232 env.PhonyTarget('prepare', [], [])
233 env.PhonyTarget('some', [], [])
236 env.Alias('all_valgrinds')
237 if env.get('HAVE_VALGRIND'):
238 for test in env.FindAllBoostUnitTests():
239 stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'),
240 [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
241 [ """$VALGRIND --tool=memcheck
243 --suppressions=${SOURCES[1]}
245 ${SOURCES[0]} --result_code=no $BOOSTTESTARGS
246 """.replace("\n"," "),
248 alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
249 env.Alias('all_valgrinds', alias)
252 env.PhonyTarget('lcov', [], [
255 ' BUILDDIR="#/build/lcov"'
256 ' CCFLAGS+="-fprofile-arcs -ftest-coverage"'
261 ' --directory $TOPDIR/build/lcov/senf'
263 ' --output-file /tmp/senf_lcov.info'
264 ' --base-directory $TOPDIR',
266 ' --output-file lcov.info'
267 ' --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*"',
269 ' --output-directory doc/lcov'
270 ' --title all_tests lcov.info',
271 'rm /tmp/senf_lcov.info' ])
272 senfutil.CleanGlob(env, ['lcov','some','all'], [ '*.gcno', '*.gcda', '*.gcov' ])
273 env.Clean(['lcov', 'all'], [ 'lcov.info', env.Dir('doc/lcov'), env.Dir('build/lcov') ])
277 env.Clean('all', ('.prepare-stamp', env.Dir('dist'), env.Dir('build')))
279 senfutil.CleanGlob(env, 'all', '$CLEAN_PATTERNS')
280 senfutil.CleanGlob(env, ['some', 'all'], '$CLEAN_SOME_PATTERNS')
282 if env.GetOption('clean') and 'all' in BUILD_TARGETS:
283 env.Depends('all', ('lcov', 'all_valgrinds'))
284 # Disable writing to the deleted .sconsign file
285 import SCons.SConsign
286 SCons.SConsign.write = lambda : None
288 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
289 Execute(Touch(".prepare-stamp"))
291 ### execute targets on remote hosts
292 for target in COMMAND_LINE_TARGETS:
294 realtarget, host = target.split('@',1)
295 cwd=env.GetLaunchDir()
296 home=os.environ['HOME']+'/'
297 if cwd.startswith(home) : cwd = cwd[len(home):]
298 args = [ '$SCONSARGS' ]
299 if env.GetLaunchDir() != os.getcwd():
301 env.PhonyTarget(target, [], [ "ssh $HOST scons $SCONSARGS -C $DIR $RTARGET" ],
302 HOST=host, RTARGET=realtarget, DIR=cwd, SCONSARGS=args)
304 env.PhonyTarget('clean', [], [
305 lambda **args: sys.stderr.write(
306 "=================================================================\n"
307 "'clean' is not a valid target, use the '-c' option instead:\n"
309 "=================================================================\n") ])