Set SCons decider to MD5-timestamp
[senf.git] / SConstruct
1 # -*- python -*-
2
3 import sys, glob, os.path, fnmatch
4 import SENFSCons, senfutil
5
6 # Fix for SCons 0.97 compatibility
7 try:
8     BoolVariable
9 except NameError:
10     BoolVariable = BoolOption
11
12 ###########################################################################
13 # Load utilities and setup libraries and configure build
14
15 env = Environment()
16
17 env.Decider('MD5-timestamp')
18
19 # Load all the local SCons tools
20 env.Tool('Doxygen')
21 env.Tool('Dia2Png')
22 env.Tool('PkgDraw')
23 env.Tool('InstallSubdir')
24 env.Tool('CopyToDir')
25 env.Tool('Boost')
26 env.Tool('CombinedObject')
27 env.Tool('PhonyTarget')
28 env.Tool('InstallDir')
29
30 env.Help("""
31 Additional top-level build targets:
32
33 prepare      Create all target files not part of the repository
34 default      Build all default targets (like calling scons with no arguments)
35 examples     Build all examples
36 all_tests    Build and run unit tests for all modules
37 all_docs     Build documentation for all modules
38 all          Build everything
39 install_all  Install SENF into $$PREFIX
40 deb          Build debian source and binary package
41 debsrc       Build debian source package
42 debbin       Build debian binary package
43 linklint     Check links of doxygen documentation with 'linklint'
44 fixlinks     Fix broken links in doxygen documentation
45 valgrind     Run all tests under valgrind/memcheck
46 """)
47
48 env.Append(
49    ENV                    = { 'PATH' : os.environ.get('PATH') },
50    CLEAN_PATTERNS         = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
51
52    CPPPATH                = [ '#' ],
53    LOCALLIBDIR            = '#',
54    LIBPATH                = [ '$LOCALLIBDIR' ],
55    LIBS                   = [ '$LIBSENF$LIBADDSUFFIX', 'rt', '$BOOSTREGEXLIB', 
56                               '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', '$BOOSTFSLIB' ], 
57    TEST_EXTRA_LIBS        = [  ],
58
59    PREFIX                 = '#/dist',
60    LIBINSTALLDIR          = '$PREFIX${syslayout and "/lib" or ""}',
61    BININSTALLDIR          = '$PREFIX${syslayout and "/bin" or ""}',
62    INCLUDEINSTALLDIR      = '$PREFIX${syslayout and "/include" or ""}',
63    CONFINSTALLDIR         = '${syslayout and "$LIBINSTALLDIR/senf" or "$PREFIX"}',
64    OBJINSTALLDIR          = '$CONFINSTALLDIR',
65    DOCINSTALLDIR          = '$PREFIX${syslayout and "/share/doc/senf" or "/manual"}',
66    SCONSINSTALLDIR        = '$CONFINSTALLDIR/site_scons',
67
68    CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
69    CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
70
71    # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
72    INLINE_OPTS_DEBUG      = [ '-finline-limit=20000', '-fvisibility-inlines-hidden', 
73                               '-fno-inline-functions', '-Winline' 
74                               '--param','large-function-growth=10000',
75                               '--param', 'large-function-insns=10000', 
76                               '--param','inline-unit-growth=10000' ],
77    INLINE_OPTS_NORMAL     = [ '-finline-limit=5000' ],
78    INLINE_OPTS            = [ '$INLINE_OPTS_NORMAL' ],
79    CXXFLAGS               = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
80                               '$CXXFLAGS_' ],
81    CXXFLAGS_              = senfutil.BuildTypeOptions('CXXFLAGS'),
82    CXXFLAGS_final         = [ '-O3' ],
83    CXXFLAGS_normal        = [ '-O0', '-g' ],
84    CXXFLAGS_debug         = [ '$CXXFLAGS_normal' ],
85
86    CPPDEFINES             = [ '$expandLogOption', '$CPPDEFINES_' ],
87    expandLogOption        = senfutil.expandLogOption,
88    CPPDEFINES_            = senfutil.BuildTypeOptions('CPPDEFINES'),
89    CPPDEFINES_final       = [ ],
90    CPPDEFINES_normal      = [ 'SENF_DEBUG' ],
91    CPPDEFINES_debug       = [ '$CPPDEFINES_normal' ],
92
93    LINKFLAGS              = [ '-rdynamic', '$LINKFLAGS_' ],
94    LINKFLAGS_             = senfutil.BuildTypeOptions('LINKFLAGS'),
95    LINKFLAGS_final        = [ ],
96    LINKFLAGS_normal       = [ '-Wl,-S' ],
97    LINKFLAGS_debug        = [ '-g' ],
98 )
99
100 env.SetDefault(
101     LIBSENF   = "senf",
102     final     = False,
103     debug     = False,
104     syslayout = False
105 )
106
107 # Set variables from command line
108 senfutil.parseArguments(
109     env,
110     BoolVariable('final', 'Build final (optimized) build', False),
111     BoolVariable('debug', 'Link in debug symbols', False),
112     BoolVariable('syslayout', 'Install in to system layout directories (lib/, include/ etc)', False),
113 )
114
115 Export('env')
116
117 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
118 # Create it even when cleaning, to silence the doxygen builder warnings
119 if not os.path.exists("Doxyfile.local"):
120     Execute(Touch("Doxyfile.local"))
121
122 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
123    and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
124     env.Execute([ "scons prepare" ])
125
126 # Load SConscripts
127
128 SConscriptChdir(0)
129 SConscript("debian/SConscript")
130 SConscriptChdir(1)
131 if os.path.exists('SConscript.local') : SConscript('SConscript.local')
132 SConscript("senf/SConscript")
133 SConscript("Examples/SConscript")
134 SConscript("HowTos/SConscript")
135 SConscript("doclib/SConscript")
136
137 ###########################################################################
138 # Define build targets
139
140 #### doc
141 env.Depends(SENFSCons.Doxygen(env), env.Value(env['ENV']['REVISION']))
142
143 #### libsenf.a
144 libsenf = env.Library("$LOCALLIBDIR/${LIBSENF}${LIBADDSUFFIX}", env['ALLOBJECTS'])
145 env.Default(libsenf)
146 env.Install('$LIBINSTALLDIR', libsenf)
147
148 def create(target, source, env): 
149     file(str(target[0]), 'w').write(source[0].get_contents()+"\n")
150 env['BUILDERS']['CreateFile'] = Builder(action = create)
151
152 conf = env.CreateFile("${LOCALLIBDIR}/${LIBSENF}${LIBADDSUFFIX}.conf", 
153                       env.Value(env.subst("$_CPPDEFFLAGS")))
154 env.Default(conf)
155 env.Install('$CONFINSTALLDIR', conf)
156
157 #### install_all, default, all_tests, all
158 env.Install('${SCONSINSTALLDIR}', [ 'site_scons/__init__.py',
159                                     'site_scons/senfutil.py',
160                                     'site_scons/yaptu.py' ])
161 env.InstallDir('${SCONSINSTALLDIR}', [ 'site_scons/site_tools', 'site_scons/lib' ],
162                FILTER_SUFFIXES=[ '','.css','.pl','.py','.sh','.sty','.xml','.xsl','.yap' ])
163 env.Install('${INCLUDEINSTALLDIR}', 'boost')
164
165 env.Alias('install_all', env.FindInstalledFiles())
166 env.Alias('default', DEFAULT_TARGETS)
167 env.Alias('all_tests', env.FindAllBoostUnitTests())
168 env.Alias('all', [ 'default', 'all_tests', 'examples', 'all_docs' ])
169
170 #### prepare
171 env.PhonyTarget('prepare', [], [])
172
173 #### valgrind
174 env.PhonyTarget('valgrind', [ 'all_tests' ], [ """
175     find -name .test.bin 
176         | while read test; do
177             echo;
178             echo "Running $$test";
179             echo;
180             valgrind --tool=memcheck --error-exitcode=99 --suppressions=valgrind.sup 
181                 $$test $BOOSTTESTARGS;
182             [ $$? -ne 99 ] || exit 1;
183         done
184 """.replace("\n"," ") ])
185
186 #### clean
187 env.Clean('all', '.prepare-stamp')
188 env.Clean('all', libsenf)
189 env.Clean('all', env.Dir('linklint')) # env.Dir to disambiguate from linklint PhonyTarget
190 env.Clean('all', env.Dir('dist'))
191
192 if env.GetOption('clean'):
193     env.Clean('all', [ os.path.join(path,f)
194                        for path, subdirs, files in os.walk('.')
195                        for pattern in env['CLEAN_PATTERNS']
196                        for f in fnmatch.filter(files,pattern) ])
197
198 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
199     Execute(Touch(".prepare-stamp"))