3 import sys, glob, os.path, datetime, pwd, time, fnmatch, string
4 sys.path.append('senfscons')
7 ###########################################################################
9 # This hack is needed for SCons V 0.96.1 compatibility. In current SCons versions
10 # we can just use 'env.AlwaysBuild(env.Alias(target), [], action)'
11 def PhonyTarget(env, target, action, sources=[]):
12 env.AlwaysBuild(env.Command(target + '.phony', [ 'SConstruct' ] + sources, env.Action(action)))
13 env.Alias(target, target + '.phony')
15 def updateRevision(target, source, env):
16 rev = env['ENV']['REVISION'][1:]
19 print "Working copy not clean. Run 'svn update'"
22 if 'm' in rev and not ARGUMENTS.get('force_deb'):
24 print "Working copy contains local changes. Commit first"
32 for line in os.popen("svn info"):
33 elts=line.split(':',1)
38 version = url.rsplit('/',1)[-1].split('_',1)[0]
39 if version[0] not in string.digits:
42 version = '1:0r%s' % rev
43 changelog = file('debian/changelog.template').read() % {
46 'user': pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0].strip(),
47 'date': time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) }
48 file('debian/changelog','w').write(changelog)
51 try: return os.stat(f).st_size > 0
52 except OSError: return False
54 def checkLocalConf(target, source, env):
55 if [ True for f in env['LOCAL_CONFIG_FILES'] if nonemptyFile(f) ]:
57 print "You have made local modifications to one of the following local configuration"
59 for f in env['LOCAL_CONFIG_FILES']:
62 print "Building a debian package would remove those files."
64 print "To continue, remove the offending file(s) and try again. Alternatively,"
65 print "build a source package using 'scons debsrc' and may then build debian"
66 print "binary packages from this source-package without disrupting your local"
67 print "configuration."
71 ###########################################################################
72 # Load utilities and setup libraries and configure build
75 SENFSCons.UseSTLPort()
76 env = SENFSCons.MakeEnvironment()
79 Additional top-level build targets:
81 prepare Create all source files not part of the repository
82 all_tests Build and run unit tests for all modules
83 all_docs Build documentation for all modules
85 install_all Install SENF into $PREFIX
86 deb Build debian source and binary package
87 debsrc Build debian source package
88 debbin Build debian binary package
89 linklint Check links of doxygen documentation with 'linklint'
90 fixlinks Fix broken links in doxygen documentation
91 valgrind Run all tests under valgrind/memcheck
94 if os.environ.get('debian_build'):
95 rev = os.popen("dpkg-parsechangelog | awk '/^Version:/{print $2}'").read().strip()
97 rev = 'r' + os.popen("svnversion").read().strip().lower()
99 logname = os.environ.get('LOGNAME')
101 logname = pwd.getpwuid(os.getuid()).pw_name
103 def dpkgIgnoredFilesOpts(target, source, env, for_signature):
104 return [ '-I%s' % os.path.split(f)[1] for f in env.subst('$DPKG_IGNORED_FILES').split() ]
106 # Options used to debug inlining:
108 # INLINE_OPTS = [ '-finline-limit=20000', '--param','large-function-growth=10000',
109 # '--param', 'large-function-insns=10000', '--param','inline-unit-growth=10000',
110 # '-fvisibility-inlines-hidden', '-fno-inline-functions', '-Winline' ]
112 # BEWARE: You need lots of ram to compile with these settings (approx 1G)
115 INLINE_OPTS = [ '-finline-limit=5000' ]
118 CPPPATH = [ '#/include' ],
119 CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS,
120 LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB' ],
121 TEST_EXTRA_LIBS = [ '$BOOSTFSLIB' ],
122 DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ],
123 DOXY_HTML_XSL = '#/doclib/html-munge.xsl',
124 ENV = { 'TODAY' : str(datetime.date.today()),
126 'LOGNAME' : logname, # needed by the debian build scripts
127 'CONCURRENCY_LEVEL' : env.GetOption('num_jobs') or "1",
129 'PATH' : os.environ.get('PATH')
131 LOCAL_CONFIG_FILES = [ 'Doxyfile.local', 'SConfig', 'local_config.hh' ],
132 DPKG_IGNORED_FILES = [ '$LOCAL_CONFIG_FILES', '.svn', '_tmplates' ],
133 DPKG_IGNORED_FILES_OPTS = dpkgIgnoredFilesOpts,
134 CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
135 BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot $DPKG_IGNORED_FILES_OPTS",
136 TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils', 'Console',
137 'config.hh', 'local_config.hh' ],
140 def parseLogOption(value):
141 stream, area, level = ( x.strip() for x in value.strip().split('|') )
142 if stream : stream = ''.join('(%s)' % x for x in stream.split('::') )
143 else : stream = '(_)'
144 if area : area = ''.join( '(%s)' % x for x in area.split('::') )
146 return '(( %s,%s,%s ))' % (stream,area,level)
148 def expandLogOption(target, source, env, for_signature):
149 return ' '.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )
151 if env.subst('$LOGLEVELS'):
152 env.Append( expandLogOption=expandLogOption )
153 env.Append( CPPDEFINES = { 'SENF_LOG_CONF': '$expandLogOption' } )
161 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
162 # Create it even when cleaning, to silence the doxygen builder warnings
163 if not os.path.exists("Doxyfile.local"):
164 Execute(Touch("Doxyfile.local"))
166 # Create local_config.h
167 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
168 Execute(Touch("local_config.hh"))
170 ###########################################################################
171 # Define build targets
173 # Before defining any targets, check wether this is the first build in
174 # pristine directory tree. If so, call 'scons prepare' so the dependencies
175 # created later are correct
177 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
178 and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
179 env.Execute([ "scons prepare" ])
181 env.Clean('all', '.prepare-stamp')
183 # Not nice, but until we get to fixing the dependency jungle
184 # concerning generated sources ...
188 SConscript(glob.glob("*/SConscript"))
190 SENFSCons.StandardTargets(env)
191 SENFSCons.GlobalTargets(env)
192 SENFSCons.Doxygen(env)
193 SENFSCons.DoxyXRef(env,
194 HTML_HEADER = '#/doclib/doxy-header.html',
195 HTML_FOOTER = '#/doclib/doxy-footer.html')
197 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
199 # Build combined library 'libsenf'
200 libsenf = env.Library(env['LIBSENF'], env['ALLOBJECTS'])
202 env.Clean('all', libsenf)
203 env.Alias('default', libsenf)
205 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
207 if env.GetOption('clean'):
208 env.Clean('all', [ os.path.join(path,f)
209 for path, subdirs, files in os.walk('.')
210 for pattern in env['CLEAN_PATTERNS']
211 for f in fnmatch.filter(files,pattern) ])
213 PhonyTarget(env, 'deb', [
216 "$BUILDPACKAGE_COMMAND",
217 "fakeroot ./debian/rules debclean"
220 PhonyTarget(env, 'debsrc', [
222 "$BUILDPACKAGE_COMMAND -S",
225 PhonyTarget(env, 'debbin', [
228 "$BUILDPACKAGE_COMMAND -b",
229 "fakeroot ./debian/rules debclean"
232 PhonyTarget(env, 'linklint', [
234 'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
235 '[ ! -r linklint/errorX.html ] || python doclib/linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
236 '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
237 '[ ! -r linklint/errorAX.html ] || python doclib/linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
238 '[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
239 'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
242 PhonyTarget(env, 'fixlinks', [
243 'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
246 PhonyTarget(env, 'prepare', [])
248 PhonyTarget(env, 'valgrind', [
249 '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'
252 env.Clean('all', env.Dir('linklint'))
254 env.Clean('all','.prepare-stamp')
255 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
256 Execute(Touch(".prepare-stamp"))