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
37 ENV = { 'PATH' : os.environ.get('PATH'), 'HOME' : os.environ.get('HOME') },
38 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
40 BUILDDIR = '${FLAVOR and "#/build/$FLAVOR" or "#"}',
41 CPPPATH = [ '$BUILDDIR', '#' ],
42 LOCALLIBDIR = '$BUILDDIR',
43 LIBPATH = [ '$LOCALLIBDIR' ],
44 LIBS = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB',
45 '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ],
46 TEST_EXTRA_LIBS = [ ],
47 VALGRINDARGS = [ '--num-callers=50' ],
50 LIBINSTALLDIR = '$PREFIX${syslayout and "/lib" or ""}',
51 BININSTALLDIR = '$PREFIX${syslayout and "/bin" or ""}',
52 INCLUDEINSTALLDIR = '$PREFIX${syslayout and "/include" or ""}',
53 CONFINSTALLDIR = '${syslayout and "$LIBINSTALLDIR/senf" or "$PREFIX"}',
54 OBJINSTALLDIR = '$CONFINSTALLDIR',
55 DOCINSTALLDIR = '$PREFIX${syslayout and "/share/doc/senf" or "/manual"}',
56 SCONSINSTALLDIR = '$CONFINSTALLDIR/site_scons',
58 CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
59 CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
61 # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
62 INLINE_OPTS_DEBUG = [ '-finline-limit=20000', '-fvisibility-inlines-hidden',
63 '-fno-inline-functions', '-Winline'
64 '--param','large-function-growth=10000',
65 '--param', 'large-function-insns=10000',
66 '--param','inline-unit-growth=10000' ],
67 INLINE_OPTS_NORMAL = [ '-finline-limit=5000' ],
68 INLINE_OPTS = [ '$INLINE_OPTS_NORMAL' ],
69 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
71 CXXFLAGS_ = senfutil.BuildTypeOptions('CXXFLAGS'),
72 CXXFLAGS_final = [ '-O3' ],
73 CXXFLAGS_normal = [ '-O0', '-g' ],
74 CXXFLAGS_debug = [ '$CXXFLAGS_normal' ],
76 CPPDEFINES = [ '$expandLogOption', '$CPPDEFINES_' ],
77 expandLogOption = senfutil.expandLogOption,
78 CPPDEFINES_ = senfutil.BuildTypeOptions('CPPDEFINES'),
79 CPPDEFINES_final = [ ],
80 CPPDEFINES_normal = [ 'SENF_DEBUG' ],
81 CPPDEFINES_debug = [ '$CPPDEFINES_normal' ],
83 LINKFLAGS = [ '-rdynamic', '$LINKFLAGS_' ],
84 LINKFLAGS_ = senfutil.BuildTypeOptions('LINKFLAGS'),
85 LINKFLAGS_final = [ ],
86 LINKFLAGS_normal = [ '-Wl,-S' ],
87 LINKFLAGS_debug = [ '-g' ],
94 SCONSBIN = env.File("#/tools/scons"),
95 SCONS = "@$SCONSBIN -Q -j$CONCURRENCY_LEVEL",
96 CONCURRENCY_LEVEL = env.GetOption('num_jobs') or 1,
97 TOPDIR = env.Dir('#').abspath,
98 LIBADDSUFFIX = '${FLAVOR and "_$FLAVOR" or ""}',
99 OBJADDSUFFIX = '${LIBADDSUFFIX}',
103 # Set variables from command line
104 senfutil.parseArguments(
106 BoolVariable('final', 'Build final (optimized) build', False),
107 BoolVariable('debug', 'Link in debug symbols', False),
108 BoolVariable('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
113 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
114 # Create it even when cleaning, to silence the doxygen builder warnings
115 if not os.path.exists("doclib/Doxyfile.local"):
116 Execute(Touch("doclib/Doxyfile.local"))
118 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
119 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
120 env.Execute([ "$SCONS prepare" ])
125 SConscript("debian/SConscript")
127 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
128 if env.subst('$BUILDDIR') == '#':
129 SConscript("SConscript")
131 SConscript("SConscript", variant_dir=env.subst('$BUILDDIR'), src_dir='#', duplicate=False)
132 SConscript("Examples/SConscript")
133 SConscript("HowTos/SConscript")
134 SConscript("doclib/SConscript")
136 ###########################################################################
137 # Define build targets
139 #### install_all, default, all_tests, all
140 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
141 'site_scons/senfutil.py',
142 'site_scons/yaptu.py' ])
143 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
144 FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
145 env.Install('${INCLUDEINSTALLDIR}', 'boost')
147 env.Alias('install_all', env.FindInstalledFiles())
148 env.Alias('default', DEFAULT_TARGETS)
149 env.Alias('all_tests', env.FindAllBoostUnitTests())
150 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
153 env.PhonyTarget('prepare', [], [])
156 for test in env.FindAllBoostUnitTests():
157 stamp = env.Command(test[0].dir.File('.test-valgrind.stamp'),
158 [ test[0].dir.File('.test.bin'), 'tools/valgrind.sup' ],
159 [ """valgrind --tool=memcheck
161 --suppressions=${SOURCES[1]}
163 ${SOURCES[0]} $BOOSTTESTARGS;
164 [ $$? -ne 99 ] || exit 1""".replace("\n"," "),
166 alias = env.Command(test[0].dir.File('valgrind'), stamp, [ env.NopAction() ])
167 env.Alias('all_valgrinds', alias)
170 env.PhonyTarget('lcov', [], [
171 '$SCONS debug=1 BUILDDIR="#/build/lcov" CCFLAGS+="-fprofile-arcs -ftest-coverage" LIBS+="gcov" all_tests',
172 '$LCOV --follow --directory $TOPDIR/build/lcov/senf --capture --output-file /tmp/senf_lcov.info --base-directory $TOPDIR',
173 '$LCOV --output-file lcov.info --remove /tmp/senf_lcov.info "*/include/*" "*/boost/*" "*.test.*" ',
174 '$GENHTML --output-directory doc/lcov --title all_tests lcov.info',
175 'rm /tmp/senf_lcov.info' ])
176 if env.GetOption('clean'):
177 env.Clean('lcov', [ os.path.join(path,f)
178 for path, subdirs, files in os.walk('.')
179 for pattern in ('*.gcno', '*.gcda', '*.gcov')
180 for f in fnmatch.filter(files,pattern) ] +
181 [ 'lcov.info', env.Dir('doc/lcov'), env.Dir('build/lcov') ])
184 env.Clean('all', ('.prepare-stamp', env.Dir('dist'), env.Dir('build')))
185 if env.GetOption('clean') : env.Depends('all', ('lcov', 'all_valgrinds'))
187 if env.GetOption('clean') and 'all' in BUILD_TARGETS:
188 env.Clean('all', [ os.path.join(path,f)
189 for path, subdirs, files in os.walk('.')
190 for pattern in env['CLEAN_PATTERNS']
191 for f in fnmatch.filter(files,pattern) ])
192 # Disable writing to the deleted .sconsign file
193 import SCons.SConsign
194 SCons.SConsign.write = lambda : None
196 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
197 Execute(Touch(".prepare-stamp"))