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' % (('/' in f) and (os.path.split(os.getcwd())[1])+f or f)
106 for f in env.subst('$DPKG_IGNORED_FILES').split() ]
108 # Options used to debug inlining:
110 # INLINE_OPTS = [ '-finline-limit=20000', '--param','large-function-growth=10000',
111 # '--param', 'large-function-insns=10000', '--param','inline-unit-growth=10000',
112 # '-fvisibility-inlines-hidden', '-fno-inline-functions', '-Winline' ]
114 # BEWARE: You need lots of ram to compile with these settings (approx 1G)
117 INLINE_OPTS = [ '-finline-limit=5000' ]
120 CPPPATH = [ '#/include' ],
121 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS,
122 LIBS = [ 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
124 TEST_EXTRA_LIBS = [ ],
125 DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ],
126 DOXY_HTML_XSL = '#/doclib/html-munge.xsl',
127 ENV = { 'TODAY' : str(datetime.date.today()),
129 'LOGNAME' : logname, # needed by the debian build scripts
130 'CONCURRENCY_LEVEL' : env.GetOption('num_jobs') or "1",
132 'PATH' : os.environ.get('PATH'),
133 'TEXINPUTS' : os.environ.get('TEXINPUTS',env.Dir('#/doclib').abspath + ':'),
135 LOCAL_CONFIG_FILES = [ '/Doxyfile.local', '/SConfig', '/local_config.hh' ],
136 DPKG_IGNORED_FILES = [ '$LOCAL_CONFIG_FILES', '.svn', '/_templates' ],
137 DPKG_IGNORED_FILES_OPTS = dpkgIgnoredFilesOpts,
138 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
139 BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot $DPKG_IGNORED_FILES_OPTS",
140 TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils', 'Console',
141 'config.hh', 'local_config.hh' ],
144 def parseLogOption(value):
145 stream, area, level = ( x.strip() for x in value.strip().split('|') )
146 if stream : stream = ''.join('(%s)' % x for x in stream.split('::') )
147 else : stream = '(_)'
148 if area : area = ''.join( '(%s)' % x for x in area.split('::') )
150 return '(( %s,%s,%s ))' % (stream,area,level)
152 def expandLogOption(target, source, env, for_signature):
153 return ' '.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )
155 if env.subst('$LOGLEVELS'):
156 env.Append( expandLogOption=expandLogOption )
157 env.Append( CPPDEFINES = { 'SENF_LOG_CONF': '$expandLogOption' } )
165 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
166 # Create it even when cleaning, to silence the doxygen builder warnings
167 if not os.path.exists("Doxyfile.local"):
168 Execute(Touch("Doxyfile.local"))
170 # Create local_config.h
171 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
172 Execute(Touch("local_config.hh"))
174 ###########################################################################
175 # Define build targets
177 # Before defining any targets, check wether this is the first build in
178 # pristine directory tree. If so, call 'scons prepare' so the dependencies
179 # created later are correct
181 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
182 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
183 env.Execute([ "scons prepare" ])
185 env.Clean('all', '.prepare-stamp')
187 SConscript(glob.glob("*/SConscript"))
189 SENFSCons.StandardTargets(env)
190 SENFSCons.GlobalTargets(env)
191 env.Depends( SENFSCons.Doxygen(env), env.Value(rev) )
192 SENFSCons.DoxyXRef(env,
193 HTML_HEADER = '#/doclib/doxy-header.html',
194 HTML_FOOTER = '#/doclib/doxy-footer.html')
196 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
198 # Build combined library 'libsenf'
199 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
201 env.Clean('all', libsenf)
202 env.Alias('default', libsenf)
204 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
206 if env.GetOption('clean'):
207 env.Clean('all', [ os.path.join(path,f)
208 for path, subdirs, files in os.walk('.')
209 for pattern in env['CLEAN_PATTERNS']
210 for f in fnmatch.filter(files,pattern) ])
212 PhonyTarget(env, 'deb', [
215 "$BUILDPACKAGE_COMMAND",
216 "fakeroot ./debian/rules debclean"
219 PhonyTarget(env, 'debsrc', [
221 "$BUILDPACKAGE_COMMAND -S",
224 PhonyTarget(env, 'debbin', [
227 "$BUILDPACKAGE_COMMAND -b",
228 "fakeroot ./debian/rules debclean"
231 PhonyTarget(env, 'linklint', [
233 'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
234 '[ ! -r linklint/errorX.html ] || python doclib/linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
235 '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
236 '[ ! -r linklint/errorAX.html ] || python doclib/linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
237 '[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
238 'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
241 PhonyTarget(env, 'fixlinks', [
242 'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
245 PhonyTarget(env, 'prepare', [ 'true' ])
247 PhonyTarget(env, 'valgrind', [
248 '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'
251 env.Clean('all', env.Dir('linklint'))
253 env.Clean('all','.prepare-stamp')
254 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
255 Execute(Touch(".prepare-stamp"))