3 import sys, glob, os.path, fnmatch
4 import SENFSCons, senfutil
6 ###########################################################################
7 # Load utilities and setup libraries and configure build
11 # Load all the local SCons tools
15 env.Tool('InstallSubdir')
18 env.Tool('CombinedObject')
19 env.Tool('PhonyTarget')
22 Additional top-level build targets:
24 prepare Create all target files not part of the repository
25 all_tests Build and run unit tests for all modules
26 all_docs Build documentation for all modules
28 install_all Install SENF into $PREFIX
29 deb Build debian source and binary package
30 debsrc Build debian source package
31 debbin Build debian binary package
32 linklint Check links of doxygen documentation with 'linklint'
33 fixlinks Fix broken links in doxygen documentation
34 valgrind Run all tests under valgrind/memcheck
37 class BuildTypeOptions:
38 def __init__(self, var):
41 def __call__(self, target, source, env, for_signature):
42 type = env['final'] and "final" or env['debug'] and "debug" or "normal"
43 return env[self._var + "_" + type]
46 PKGDRAW = 'doclib/pkgdraw',
50 ENV = { 'PATH' : os.environ.get('PATH') },
51 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*', '.sconsign' ],
53 CPPPATH = [ '#/include' ],
55 LIBPATH = [ '$LOCALLIBDIR' ],
56 LIBS = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB',
57 '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ],
58 TEST_EXTRA_LIBS = [ ],
60 PREFIX = '/usr/local',
61 LIBINSTALLDIR = '$PREFIX/lib',
62 BININSTALLDIR = '$PREFIX/bin',
63 INCLUDEINSTALLDIR = '$PREFIX/include',
64 OBJINSTALLDIR = '$LIBINSTALLDIR',
65 DOCINSTALLDIR = '$PREFIX/doc',
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_ = 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_ = BuildTypeOptions('CPPDEFINES'),
87 CPPDEFINES_final = [ ],
88 CPPDEFINES_normal = [ 'SENF_DEBUG' ],
89 CPPDEFINES_debug = [ '$CPPDEFINES_normal' ],
91 LINKFLAGS = [ '-rdynamic', '$LINKFLAGS_' ],
92 LINKFLAGS_ = BuildTypeOptions('LINKFLAGS'),
93 LINKFLAGS_final = [ ],
94 LINKFLAGS_normal = [ '-Wl,-S' ],
95 LINKFLAGS_debug = [ ],
104 # Set variables from command line
105 env.Replace(**ARGUMENTS)
109 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
110 # Create it even when cleaning, to silence the doxygen builder warnings
111 if not os.path.exists("Doxyfile.local"):
112 Execute(Touch("Doxyfile.local"))
114 # Create local_config.h
115 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
116 Execute(Touch("local_config.hh"))
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" ])
122 # Load SConscripts. Need to load some first (they change the global environment)
128 SConscript(initSConscripts)
130 if os.path.exists('SConscript.local'):
131 SConscript('SConscript.local')
133 SConscript(list(set(glob.glob("*/SConscript")) - set(initSConscripts)))
135 ###########################################################################
136 # Define build targets
139 env.Depends(SENFSCons.Doxygen(env), env.Value(env['ENV']['REVISION']))
142 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
145 env.InstallSubdir(target = '$INCLUDEINSTALLDIR', source = [ 'config.hh' ])
146 env.Install('$LIBINSTALLDIR', libsenf)
148 #### install_all, default, all_tests, all
149 env.Alias('install_all', env.FindInstalledFiles())
150 env.Alias('default', DEFAULT_TARGETS)
151 env.Alias('all_tests', env.FindAllBoostUnitTests())
152 env.Alias('all', [ 'default', 'all_tests', 'all_docs' ])
155 env.PhonyTarget('prepare', [], [])
158 env.PhonyTarget('valgrind', [ 'all_tests' ], [ """
160 | while read test; do
162 echo "Running $$test";
164 valgrind --tool=memcheck --error-exitcode=99 --suppressions=valgrind.sup
165 $$test $BOOSTTESTARGS;
166 [ $$? -ne 99 ] || exit 1;
168 """.replace("\n"," ") ])
171 env.Clean('all', '.prepare-stamp')
172 env.Clean('all', libsenf)
173 env.Clean('all', env.Dir('linklint')) # env.Dir to disambiguate from linklint PhonyTarget
175 if env.GetOption('clean'):
176 env.Clean('all', [ os.path.join(path,f)
177 for path, subdirs, files in os.walk('.')
178 for pattern in env['CLEAN_PATTERNS']
179 for f in fnmatch.filter(files,pattern) ])
181 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
182 Execute(Touch(".prepare-stamp"))