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