3 import sys, glob, os.path, datetime, pwd, time, fnmatch, string
4 sys.path.append(Dir('#/senfscons').abspath)
5 sys.path.append(Dir('#/doclib').abspath)
8 ###########################################################################
10 # This hack is needed for SCons V 0.96.1 compatibility. In current SCons versions
11 # we can just use 'env.AlwaysBuild(env.Alias(target), [], action)'
12 def PhonyTarget(env, target, action, sources=[]):
13 env.AlwaysBuild(env.Command(target + '.phony', [ 'SConstruct' ] + sources, env.Action(action)))
14 env.Alias(target, target + '.phony')
16 def updateRevision(target, source, env):
17 rev = env['ENV']['REVISION'][1:]
20 print "Working copy not clean. Run 'svn update'"
23 if 'm' in rev and not ARGUMENTS.get('force_deb'):
25 print "Working copy contains local changes. Commit first"
33 for line in os.popen("svn info"):
34 elts=line.split(':',1)
39 version = url.rsplit('/',1)[-1].split('_',1)[0]
40 if version[0] not in string.digits:
43 version = '1:0r%s' % rev
44 changelog = file('debian/changelog.template').read() % {
47 'user': pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0].strip(),
48 'date': time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) }
49 file('debian/changelog','w').write(changelog)
52 try: return os.stat(f).st_size > 0
53 except OSError: return False
55 def checkLocalConf(target, source, env):
56 if [ True for f in env['LOCAL_CONFIG_FILES'] if nonemptyFile(f) ]:
58 print "You have made local modifications to one of the following local configuration"
60 for f in env['LOCAL_CONFIG_FILES']:
63 print "Building a debian package would remove those files."
65 print "To continue, remove the offending file(s) and try again. Alternatively,"
66 print "build a source package using 'scons debsrc' and may then build debian"
67 print "binary packages from this source-package without disrupting your local"
68 print "configuration."
72 ###########################################################################
73 # Load utilities and setup libraries and configure build
76 SENFSCons.UseSTLPort()
77 env = SENFSCons.MakeEnvironment()
80 Additional top-level build targets:
82 prepare Create all source files not part of the repository
83 all_tests Build and run unit tests for all modules
84 all_docs Build documentation for all modules
86 install_all Install SENF into $PREFIX
87 deb Build debian source and binary package
88 debsrc Build debian source package
89 debbin Build debian binary package
90 linklint Check links of doxygen documentation with 'linklint'
91 fixlinks Fix broken links in doxygen documentation
92 valgrind Run all tests under valgrind/memcheck
95 if os.environ.get('debian_build'):
96 rev = os.popen("dpkg-parsechangelog | awk '/^Version:/{print $2}'").read().strip()
98 rev = 'r' + os.popen("svnversion").read().strip().lower()
100 logname = os.environ.get('LOGNAME')
102 logname = pwd.getpwuid(os.getuid()).pw_name
104 def dpkgIgnoredFilesOpts(target, source, env, for_signature):
105 return [ '-I%s' % os.path.split(f)[1] for f in env.subst('$DPKG_IGNORED_FILES').split() ]
107 # Options used to debug inlining:
109 # INLINE_OPTS = [ '-finline-limit=20000', '--param','large-function-growth=10000',
110 # '--param', 'large-function-insns=10000', '--param','inline-unit-growth=10000',
111 # '-fvisibility-inlines-hidden', '-fno-inline-functions', '-Winline' ]
113 # BEWARE: You need lots of ram to compile with these settings (approx 1G)
116 INLINE_OPTS = [ '-finline-limit=5000' ]
119 CPPPATH = [ '#/include' ],
120 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS,
121 LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB' ],
122 TEST_EXTRA_LIBS = [ '$BOOSTFSLIB' ],
123 DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ],
124 DOXY_HTML_XSL = '#/doclib/html-munge.xsl',
125 ENV = { 'TODAY' : str(datetime.date.today()),
127 'LOGNAME' : logname, # needed by the debian build scripts
128 'CONCURRENCY_LEVEL' : env.GetOption('num_jobs') or "1",
130 'PATH' : os.environ.get('PATH')
132 LOCAL_CONFIG_FILES = [ 'Doxyfile.local', 'SConfig', 'local_config.hh' ],
133 DPKG_IGNORED_FILES = [ '$LOCAL_CONFIG_FILES', '.svn', '_templates' ],
134 DPKG_IGNORED_FILES_OPTS = dpkgIgnoredFilesOpts,
135 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
136 BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot $DPKG_IGNORED_FILES_OPTS",
137 TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils', 'Console',
138 'config.hh', 'local_config.hh' ],
141 def parseLogOption(value):
142 stream, area, level = ( x.strip() for x in value.strip().split('|') )
143 if stream : stream = ''.join('(%s)' % x for x in stream.split('::') )
144 else : stream = '(_)'
145 if area : area = ''.join( '(%s)' % x for x in area.split('::') )
147 return '(( %s,%s,%s ))' % (stream,area,level)
149 def expandLogOption(target, source, env, for_signature):
150 return ' '.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )
152 if env.subst('$LOGLEVELS'):
153 env.Append( expandLogOption=expandLogOption )
154 env.Append( CPPDEFINES = { 'SENF_LOG_CONF': '$expandLogOption' } )
162 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
163 # Create it even when cleaning, to silence the doxygen builder warnings
164 if not os.path.exists("Doxyfile.local"):
165 Execute(Touch("Doxyfile.local"))
167 # Create local_config.h
168 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
169 Execute(Touch("local_config.hh"))
171 ###########################################################################
172 # Define build targets
174 # Before defining any targets, check wether this is the first build in
175 # pristine directory tree. If so, call 'scons prepare' so the dependencies
176 # created later are correct
178 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
179 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
180 env.Execute([ "scons prepare" ])
182 env.Clean('all', '.prepare-stamp')
184 # Not nice, but until we get to fixing the dependency jungle
185 # concerning generated sources ...
189 SConscript(glob.glob("*/SConscript"))
191 SENFSCons.StandardTargets(env)
192 SENFSCons.GlobalTargets(env)
193 SENFSCons.Doxygen(env)
194 SENFSCons.DoxyXRef(env,
195 HTML_HEADER = '#/doclib/doxy-header.html',
196 HTML_FOOTER = '#/doclib/doxy-footer.html')
198 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
200 # Build combined library 'libsenf'
201 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
203 env.Clean('all', libsenf)
204 env.Alias('default', libsenf)
206 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
208 if env.GetOption('clean'):
209 env.Clean('all', [ os.path.join(path,f)
210 for path, subdirs, files in os.walk('.')
211 for pattern in env['CLEAN_PATTERNS']
212 for f in fnmatch.filter(files,pattern) ])
214 PhonyTarget(env, 'deb', [
217 "$BUILDPACKAGE_COMMAND",
218 "fakeroot ./debian/rules debclean"
221 PhonyTarget(env, 'debsrc', [
223 "$BUILDPACKAGE_COMMAND -S",
226 PhonyTarget(env, 'debbin', [
229 "$BUILDPACKAGE_COMMAND -b",
230 "fakeroot ./debian/rules debclean"
233 PhonyTarget(env, 'linklint', [
235 'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
236 '[ ! -r linklint/errorX.html ] || python doclib/linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
237 '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
238 '[ ! -r linklint/errorAX.html ] || python doclib/linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
239 '[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
240 'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
243 PhonyTarget(env, 'fixlinks', [
244 'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
247 PhonyTarget(env, 'prepare', [])
249 PhonyTarget(env, 'valgrind', [
250 'find -name .test.bin | while read test; do echo; echo "Running $$test"; echo; valgrind --tool=memcheck --error-exitcode=99 --suppressions=valgrind.sup $$test $BOOSTTESTARGS; [ $$? -ne 99 ] || exit 1; done'
253 env.Clean('all', env.Dir('linklint'))
255 env.Clean('all','.prepare-stamp')
256 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
257 Execute(Touch(".prepare-stamp"))