PPI: Rename all 'Reader's to 'Source's and 'Writer's to 'Sink's
[senf.git] / SConstruct
1 # -*- python -*-
2
3 import sys, glob, os.path, datetime, pwd, time, fnmatch
4 sys.path.append('senfscons')
5 import SENFSCons
6
7 ###########################################################################
8
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):
12     env.AlwaysBuild(env.Command(target + '.phony', 'SConstruct', env.Action(action)))
13     env.Alias(target, target + '.phony')
14
15 def updateRevision(target, source, env):
16     rev = env['ENV']['REVISION'][1:]
17     if ':' in rev:
18         print
19         print "Working copy not clean. Run 'svn update'"
20         print
21         return 1
22     if 'm' in rev and not ARGUMENTS.get('force_deb'):
23         print
24         print "Working copy contains local changes. Commit first"
25         print
26         return 1
27     if 's' in rev:
28         rev = rev[:-1]
29     if 'm' in rev:
30         rev = rev[:-1]
31     changelog = file('debian/changelog.template').read() % {
32         'rev': rev,
33         'user': pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0].strip(),
34         'date': time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) }
35     file('debian/changelog','w').write(changelog)
36
37 def nonemptyFile(f):
38     try: return os.stat(f).st_size > 0
39     except OSError: return False
40
41 def checkLocalConf(target, source, env):
42     if [ True for f in env['CONFIG_FILES'] if nonemptyFile(f) ]:
43         print
44         print "You have made local modifications to 'SConfig' and/or 'Doxyfile.local'."
45         print "Building a debian package would remove those files."
46         print
47         print "To continue, remove the offending file(s) and try again. Alternatively,"
48         print "build a source package using 'scons debsrc' and may then build debian"
49         print "binary packages from this source-package without disrupting your print local"
50         print "configuration."
51         print
52         return 1
53
54 ###########################################################################
55 # Load utilities and setup libraries and configure build
56
57 SENFSCons.UseBoost()
58 SENFSCons.UseSTLPort()
59 env = SENFSCons.MakeEnvironment()
60
61 env.Help("""
62 Additional top-level build targets:
63
64 prepare      Create all source files not part of the repository
65 all_tests    Build and run unit tests for all modules
66 all_docs     Build documentation for all modules
67 all          Build everything
68 install_all  Install SENF into $PREFIX
69 deb          Build debian source and binary package
70 debsrc       Build debian source package
71 debbin       Build debian binary package
72 linklint     Check links of doxygen documentation with 'linklint'
73 """)
74
75 if os.environ.get('debian_build'):
76     rev = os.popen("dpkg-parsechangelog | awk '/^Version:/{print $2}'").read().strip()
77 else:
78     rev = 'r' + os.popen("svnversion").read().strip().lower()
79
80 logname = os.environ.get('LOGNAME')
81 if not logname:
82     logname = pwd.getpwuid(os.getuid()).pw_name
83
84 def configFilesOpts(target, source, env, for_signature):
85     return [ '-I%s' % os.path.split(f)[1] for f in env['CONFIG_FILES'] ]
86
87 env.Append(
88    CPPPATH = [ '#/include' ],
89    LIBS = [ 'iberty', '$BOOSTREGEXLIB' ],
90    DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ],
91    DOXY_HTML_XSL = '#/doclib/html-munge.xsl',
92    ENV = { 'TODAY' : str(datetime.date.today()),
93            'REVISION' : rev,
94            'LOGNAME' : logname, # needed by the debian build scripts
95            'CONCURRENCY_LEVEL' : env.GetOption('num_jobs') or "1",
96            'SCONS' : 1
97            },
98    CONFIG_FILES = [ 'Doxyfile.local', 'SConfig', 'local_config.hh' ],
99    CONFIG_FILES_OPTS = configFilesOpts,
100    CLEAN_PATTERNS = [ '*.pyc', 'semantic.cache', '.sconsign', '.sconsign.dblite' ],
101    BUILDPACKAGE_COMMAND = "dpkg-buildpackage -us -uc -rfakeroot -I.svn $CONFIG_FILES_OPTS",
102    TOP_INCLUDES = [ 'Packets', 'PPI', 'Scheduler', 'Socket', 'Utils',
103                     'config.hh', 'local_config.hh' ]
104 )
105
106 Export('env')
107
108 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
109 if not env.GetOption('clean') and not os.path.exists("Doxyfile.local"):
110     Execute(Touch("Doxyfile.local"))
111
112 # Create local_config.h
113 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
114     Execute(Touch("local_config.hh"))
115
116 ###########################################################################
117 # Define build targets
118
119 # Before defining any targets, check wether this is the first build in
120 # pristine directory tree. If so, call 'scons prepare' so the dependencies
121 # created later are correct
122
123 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
124    and not os.environ.get("SCONS"):
125     env.Execute([ "scons prepare" ])
126
127 env.Clean('all', '.prepare-stamp')
128
129 SConscript(glob.glob("*/SConscript"))
130
131 SENFSCons.StandardTargets(env)
132 SENFSCons.GlobalTargets(env)
133 SENFSCons.Doxygen(env)
134 SENFSCons.DoxyXRef(env,
135                    HTML_HEADER = '#/doclib/doxy-header-overview.html',
136                    HTML_FOOTER = '#/doclib/doxy-footer.html')
137
138 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
139
140 # Build combined library 'libsenf'
141 libsenf = env.Library(
142     SENFSCons.LibPath('senf'),
143     Flatten([ env.File(SENFSCons.LibPath(lib)).sources for lib in env['ALLLIBS'] ]))
144 env.Default(libsenf)
145 env.Clean('all', 'libsenf.a')
146 env.Alias('default', 'libsenf.a')
147
148 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
149
150 env.Clean('all', [ os.path.join(path,f)
151                    for path, subdirs, files in os.walk('.')
152                    for pattern in env['CLEAN_PATTERNS']
153                    for f in fnmatch.filter(files,pattern) ])
154
155 PhonyTarget(env, 'deb', [
156     checkLocalConf,
157     updateRevision,
158     "$BUILDPACKAGE_COMMAND",
159 ])
160
161 PhonyTarget(env, 'debsrc', [
162     updateRevision,
163     "$BUILDPACKAGE_COMMAND -S",
164 ])
165
166 PhonyTarget(env, 'debbin', [
167     checkLocalConf,
168     updateRevision,
169     "$BUILDPACKAGE_COMMAND -nc",
170 ])
171
172 PhonyTarget(env, 'linklint', [
173     'rm -rf linklint',
174     'linklint -doc linklint -net -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
175     '[ ! -r linklint/errorX.html ] || python linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
176     '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
177     '[ ! -r linklint/errorAX.html ] || python linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
178     '[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
179     'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
180 ])
181
182 PhonyTarget(env, 'fixlinks', [
183     'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
184 ])
185
186 PhonyTarget(env, 'prepare', [])
187
188 env.Clean('all', env.Dir('linklint'))
189
190 env.Clean('all','.prepare-stamp')
191 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
192     Execute(Touch(".prepare-stamp"))