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