doclib: Remove unneeded latex package import from pkgdraw
[senf.git] / SConstruct
1 # -*- python -*-
2
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)
6 import SENFSCons
7
8 ###########################################################################
9
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')
15
16 def updateRevision(target, source, env):
17     rev = env['ENV']['REVISION'][1:]
18     if ':' in rev:
19         print
20         print "Working copy not clean. Run 'svn update'"
21         print
22         return 1
23     if 'm' in rev and not ARGUMENTS.get('force_deb'):
24         print
25         print "Working copy contains local changes. Commit first"
26         print
27         return 1
28     if 's' in rev:
29         rev = rev[:-1]
30     if 'm' in rev:
31         rev = rev[:-1]
32     url = None
33     for line in os.popen("svn info"):
34         elts=line.split(':',1)
35         if elts[0] == 'URL':
36             url = elts[1].strip()
37     version = None
38     if '/tags/' in url:
39         version = url.rsplit('/',1)[-1].split('_',1)[0]
40         if version[0] not in string.digits:
41             version = None
42     if version is None:
43         version = '1:0r%s' % rev
44     changelog = file('debian/changelog.template').read() % {
45         'version': version,
46         'rev': rev,
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)
50
51 def nonemptyFile(f):
52     try: return os.stat(f).st_size > 0
53     except OSError: return False
54
55 def checkLocalConf(target, source, env):
56     if [ True for f in env['LOCAL_CONFIG_FILES'] if nonemptyFile(f) ]:
57         print
58         print "You have made local modifications to one of the following local configuration"
59         print "files:"
60         for f in env['LOCAL_CONFIG_FILES']:
61             print "    ",f
62         print
63         print "Building a debian package would remove those files."
64         print
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."
69         print
70         return 1
71
72 ###########################################################################
73 # Load utilities and setup libraries and configure build
74
75 SENFSCons.UseBoost()
76 SENFSCons.UseSTLPort()
77 env = SENFSCons.MakeEnvironment()
78
79 env.Help("""
80 Additional top-level build targets:
81
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
85 all          Build everything
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
93 """)
94
95 if os.environ.get('debian_build'):
96     rev = os.popen("dpkg-parsechangelog | awk '/^Version:/{print $2}'").read().strip()
97 else:
98     rev = 'r' + os.popen("svnversion").read().strip().lower()
99
100 logname = os.environ.get('LOGNAME')
101 if not logname:
102     logname = pwd.getpwuid(os.getuid()).pw_name
103
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() ]
106
107 # Options used to debug inlining:
108 #
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' ]
112 #
113 # BEWARE: You need lots of ram to compile with these settings (approx 1G)
114 #
115
116 INLINE_OPTS = [ '-finline-limit=5000' ]
117
118 env.Append(
119    CPPPATH = [ '#/include' ],
120    CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS,
121    LIBS = [ 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
122             '$BOOSTFSLIB' ],
123    TEST_EXTRA_LIBS = [ ],
124    DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ],
125    DOXY_HTML_XSL = '#/doclib/html-munge.xsl',
126    ENV = { 'TODAY' : str(datetime.date.today()),
127            'REVISION' : rev,
128            'LOGNAME' : logname, # needed by the debian build scripts
129            'CONCURRENCY_LEVEL' : env.GetOption('num_jobs') or "1",
130            'SCONS' : 1,
131            'PATH' : os.environ.get('PATH'),
132            'TEXINPUTS' : os.environ.get('TEXINPUTS'),
133          },
134    LOCAL_CONFIG_FILES = [ 'Doxyfile.local', 'SConfig', 'local_config.hh' ],
135    DPKG_IGNORED_FILES = [ '$LOCAL_CONFIG_FILES', '.svn', '_templates' ],
136    DPKG_IGNORED_FILES_OPTS = dpkgIgnoredFilesOpts,
137    CLEAN_PATTERNS = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
138    BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot $DPKG_IGNORED_FILES_OPTS",
139    TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils', 'Console',
140                     'config.hh', 'local_config.hh' ],
141 )
142
143 def parseLogOption(value):
144     stream, area, level = ( x.strip() for x in value.strip().split('|') )
145     if stream  : stream = ''.join('(%s)' % x for x in stream.split('::') )
146     else       : stream = '(_)'
147     if area : area = ''.join( '(%s)' % x for x in area.split('::') )
148     else    : area = '(_)'
149     return '(( %s,%s,%s ))' % (stream,area,level)
150
151 def expandLogOption(target, source, env, for_signature):
152     return ' '.join( parseLogOption(x) for x in env.subst('$LOGLEVELS').split() )
153
154 if env.subst('$LOGLEVELS'):
155     env.Append( expandLogOption=expandLogOption )
156     env.Append( CPPDEFINES = { 'SENF_LOG_CONF': '$expandLogOption' } )
157
158 env.SetDefault(
159        LIBSENF = "senf"
160 )
161
162 Export('env')
163
164 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
165 # Create it even when cleaning, to silence the doxygen builder warnings
166 if not os.path.exists("Doxyfile.local"):
167     Execute(Touch("Doxyfile.local"))
168
169 # Create local_config.h
170 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
171     Execute(Touch("local_config.hh"))
172
173 ###########################################################################
174 # Define build targets
175
176 # Before defining any targets, check wether this is the first build in
177 # pristine directory tree. If so, call 'scons prepare' so the dependencies
178 # created later are correct
179
180 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
181    and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
182     env.Execute([ "scons prepare" ])
183
184 env.Clean('all', '.prepare-stamp')
185
186 # Not nice, but until we get to fixing the dependency jungle
187 # concerning generated sources ...
188 scripts = []
189 dependencies = []
190
191 SConscript(glob.glob("*/SConscript"))
192
193 SENFSCons.StandardTargets(env)
194 SENFSCons.GlobalTargets(env)
195 SENFSCons.Doxygen(env)
196 SENFSCons.DoxyXRef(env,
197                    HTML_HEADER = '#/doclib/doxy-header.html',
198                    HTML_FOOTER = '#/doclib/doxy-footer.html')
199
200 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
201
202 # Build combined library 'libsenf'
203 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
204 env.Default(libsenf)
205 env.Clean('all', libsenf)
206 env.Alias('default', libsenf)
207
208 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
209
210 if env.GetOption('clean'):
211     env.Clean('all', [ os.path.join(path,f)
212                        for path, subdirs, files in os.walk('.')
213                        for pattern in env['CLEAN_PATTERNS']
214                        for f in fnmatch.filter(files,pattern) ])
215
216 PhonyTarget(env, 'deb', [
217     checkLocalConf,
218     updateRevision,
219     "$BUILDPACKAGE_COMMAND",
220     "fakeroot ./debian/rules debclean"
221 ])
222
223 PhonyTarget(env, 'debsrc', [
224     updateRevision,
225     "$BUILDPACKAGE_COMMAND -S",
226 ])
227
228 PhonyTarget(env, 'debbin', [
229     checkLocalConf,
230     updateRevision,
231     "$BUILDPACKAGE_COMMAND -b",
232     "fakeroot ./debian/rules debclean"
233 ])
234
235 PhonyTarget(env, 'linklint', [
236     'rm -rf linklint',
237     'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
238     '[ ! -r linklint/errorX.html ] || python doclib/linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
239     '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
240     '[ ! -r linklint/errorAX.html ] || python doclib/linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
241     '[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
242     'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
243 ])
244
245 PhonyTarget(env, 'fixlinks', [
246     'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
247 ])
248
249 PhonyTarget(env, 'prepare', [])
250
251 PhonyTarget(env, 'valgrind', [
252     '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     ], [ 'all_tests' ])
254
255 env.Clean('all', env.Dir('linklint'))
256
257 env.Clean('all','.prepare-stamp')
258 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
259     Execute(Touch(".prepare-stamp"))