3 import sys, 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
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 all_docs Build documentation for all modules
26 install_all Install SENF into $$PREFIX
27 deb Build debian source and binary package
28 debsrc Build debian source package
29 debbin Build debian binary package
30 linklint Check links of doxygen documentation with 'linklint'
31 fixlinks Fix broken links in doxygen documentation
32 all_valgrinds Run all tests under valgrind/memcheck
33 lcov Generate test coverage output in doc/lcov and lcov.info
35 You may execute targets on a remote host (if the directory layout is the same)
38 scons <target>@[<user>@]<host>
42 ENV = { 'PATH' : os.environ.get('PATH'),
43 'HOME' : os.environ.get('HOME'),
44 'SSH_AGENT_PID': os.environ.get('SSH_AGENT_PID'),
45 'SSH_AUTH_SOCK': os.environ.get('SSH_AUTH_SOCK') },
46 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
48 BUILDDIR = '${FLAVOR and "#/build/$FLAVOR" or "#"}',
49 CPPPATH = [ '$BUILDDIR', '#' ],
50 LOCALLIBDIR = '$BUILDDIR',
51 LIBPATH = [ '$LOCALLIBDIR' ],
52 LIBS = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB',
53 '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ],
54 TEST_EXTRA_LIBS = [ ],
55 VALGRINDARGS = [ '--num-callers=50' ],
58 LIBINSTALLDIR = '$PREFIX${syslayout and "/lib" or ""}',
59 BININSTALLDIR = '$PREFIX${syslayout and "/bin" or ""}',
60 INCLUDEINSTALLDIR = '$PREFIX${syslayout and "/include" or ""}',
61 CONFINSTALLDIR = '${syslayout and "$LIBINSTALLDIR/senf" or "$PREFIX"}',
62 OBJINSTALLDIR = '$CONFINSTALLDIR',
63 DOCINSTALLDIR = '$PREFIX${syslayout and "/share/doc/senf" or "/manual"}',
64 SCONSINSTALLDIR = '$CONFINSTALLDIR/site_scons',
66 CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
67 CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
69 # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
70 INLINE_OPTS_DEBUG = [ '-finline-limit=20000', '-fvisibility-inlines-hidden',
71 '-fno-inline-functions', '-Winline'
72 '--param','large-function-growth=10000',
73 '--param', 'large-function-insns=10000',
74 '--param','inline-unit-growth=10000' ],
75 INLINE_OPTS_NORMAL = [ '-finline-limit=5000' ],
76 INLINE_OPTS = [ '$INLINE_OPTS_NORMAL' ],
77 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
79 CXXFLAGS_ = senfutil.BuildTypeOptions('CXXFLAGS'),
80 CXXFLAGS_final = [ '-O3' ],
81 CXXFLAGS_normal = [ '-O0', '-g' ],
82 CXXFLAGS_debug = [ '$CXXFLAGS_normal' ],
84 CPPDEFINES = [ '$expandLogOption', '$CPPDEFINES_' ],
85 expandLogOption = senfutil.expandLogOption,
86 CPPDEFINES_ = senfutil.BuildTypeOptions('CPPDEFINES'),
87 CPPDEFINES_final = [ ],
88 CPPDEFINES_normal = [ 'SENF_DEBUG' ],
89 CPPDEFINES_debug = [ '$CPPDEFINES_normal' ],
91 LINKFLAGS = [ '-rdynamic', '$LINKFLAGS_' ],
92 LINKFLAGS_ = senfutil.BuildTypeOptions('LINKFLAGS'),
93 LINKFLAGS_final = [ ],
94 LINKFLAGS_normal = [ '-Wl,-S' ],
95 LINKFLAGS_debug = [ '-g' ],
102 SCONSBIN = env.File("#/tools/scons"),
103 SCONSARGS = [ '-Q', '-j$CONCURRENCY_LEVEL', 'debug=$debug', 'final=$final' ],
104 SCONS = "@$SCONSBIN $SCONSARGS",
105 CONCURRENCY_LEVEL = env.GetOption('num_jobs') or 1,
106 TOPDIR = env.Dir('#').abspath,
107 LIBADDSUFFIX = '${FLAVOR and "_$FLAVOR" or ""}',
108 OBJADDSUFFIX = '${LIBADDSUFFIX}',
112 # Set variables from command line
113 senfutil.parseArguments(
115 BoolVariable('final', 'Build final (optimized) build', False),
116 BoolVariable('debug', 'Link in debug symbols', False),
117 BoolVariable('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
122 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
123 # Create it even when cleaning, to silence the doxygen builder warnings
124 if not os.path.exists("doclib/Doxyfile.local"):
125 Execute(Touch("doclib/Doxyfile.local"))
127 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
128 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
129 env.Execute([ "$SCONS prepare" ])
134 SConscript("debian/SConscript")
136 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
137 if env.subst('$BUILDDIR') == '#':
138 SConscript("SConscript")
140 SConscript("SConscript", variant_dir=env.subst('$BUILDDIR'), src_dir='#', duplicate=False)
141 SConscript("Examples/SConscript")
142 SConscript("HowTos/SConscript")
143 SConscript("doclib/SConscript")
145 ###########################################################################
146 # Define build targets
148 #### install_all, default, all_tests, all
149 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
150 'site_scons/senfutil.py',
151 'site_scons/yaptu.py' ])
152 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
153 FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
154 env.Install('${INCLUDEINSTALLDIR}', 'boost')
156 env.Alias('install_all', env.FindInstalledFiles())
157 env.Alias('default', DEFAULT_TARGETS)
158 env.Alias('all_tests', env.FindAllBoostUnitTests())
159 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
162 env.PhonyTarget('prepare', [], [])
165 for test in env.FindAllBoostUnitTests():
166 stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'),
167 [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
168 [ """valgrind --tool=memcheck
170 --suppressions=${SOURCES[1]}
172 ${SOURCES[0]} $BOOSTTESTARGS;
173 [ $$? -ne 99 ] || exit 1""".replace("\n"," "),
175 alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
176 env.Alias('all_valgrinds', alias)
179 env.PhonyTarget('lcov', [], [
180 '$SCONS debug=1 BUILDDIR="#/build/lcov" CCFLAGS+="-fprofile-arcs -ftest-coverage" LIBS+="gcov" all_tests',
181 '$LCOV --follow --directory $TOPDIR/build/lcov/senf --capture --output-file /tmp/senf_lcov.info --base-directory $TOPDIR',
182 '$LCOV --output-file lcov.info --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*" ',
183 '$GENHTML --output-directory doc/lcov --title all_tests lcov.info',
184 'rm /tmp/senf_lcov.info' ])
185 if env.GetOption('clean'):
186 env.Clean('lcov', [ os.path.join(path,f)
187 for path, subdirs, files in os.walk('.')
188 for pattern in ('*.gcno', '*.gcda', '*.gcov')
189 for f in fnmatch.filter(files,pattern) ] +
190 [ 'lcov.info', env.Dir('doc/lcov'), env.Dir('build/lcov') ])
193 env.Clean('all', ('.prepare-stamp', env.Dir('dist'), env.Dir('build')))
194 if env.GetOption('clean') : env.Depends('all', ('lcov', 'all_valgrinds'))
196 if env.GetOption('clean') and 'all' in BUILD_TARGETS:
197 env.Clean('all', [ os.path.join(path,f)
198 for path, subdirs, files in os.walk('.')
199 for pattern in env['CLEAN_PATTERNS']
200 for f in fnmatch.filter(files,pattern) ])
201 # Disable writing to the deleted .sconsign file
202 import SCons.SConsign
203 SCons.SConsign.write = lambda : None
205 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
206 Execute(Touch(".prepare-stamp"))
208 ### execute targets on remote hosts
209 for target in COMMAND_LINE_TARGETS:
211 realtarget, host = target.split('@',1)
212 cwd=env.GetLaunchDir()
213 home=os.environ['HOME']+'/'
214 if cwd.startswith(home) : cwd = cwd[len(home):]
215 args = [ '$SCONSARGS' ]
216 if env.GetLaunchDir() != os.getcwd():
218 env.PhonyTarget(target, [], [ "ssh $HOST scons $SCONSARGS -C $DIR $RTARGET" ],
219 HOST=host, RTARGET=realtarget, DIR=cwd, SCONSARGS=args)