Move all build env settings from SENFSCons to SConstruct
[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, senfutil
7
8 ###########################################################################
9 # Load utilities and setup libraries and configure build
10
11 env = Environment()
12
13 # Load all the local SCons tools
14 env.Tool('Doxygen', [ 'senfscons' ])
15 env.Tool('Dia2Png', [ 'senfscons' ])
16 env.Tool('PkgDraw', [ 'senfscons' ])
17 env.Tool('CopyToDir', [ 'senfscons' ])
18 env.Tool('ProgramNoScan', [ 'senfscons' ])
19 env.Tool('CompileCheck', [ 'senfscons' ])
20 env.Tool('Boost', [ 'senfscons' ])
21 env.Tool('BoostUnitTests', [ 'senfscons' ])
22
23 env.Help("""
24 Additional top-level build targets:
25
26 prepare      Create all source files not part of the repository
27 all_tests    Build and run unit tests for all modules
28 all_docs     Build documentation for all modules
29 all          Build everything
30 install_all  Install SENF into $PREFIX
31 deb          Build debian source and binary package
32 debsrc       Build debian source package
33 debbin       Build debian binary package
34 linklint     Check links of doxygen documentation with 'linklint'
35 fixlinks     Fix broken links in doxygen documentation
36 valgrind     Run all tests under valgrind/memcheck
37 """)
38
39 # Compile options
40
41 # Options used to debug inlining:
42 #
43 # BEWARE: You need lots of ram to compile with these settings (approx 1G)
44
45 class BuildTypeOptions:
46     def __init__(self, var):
47         self._var = var
48
49     def __call__(self, source, target, env, for_signature):
50         type = env['final'] and "final" or env['debug'] and "debug" or "normal"
51         return env[self._var + "_" + type]
52
53 env.Append(
54    ENV                    = { 'PATH' : os.environ.get('PATH') },
55    CLEAN_PATTERNS         = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*' ],
56
57    CPPPATH                = [ '#/include' ],
58    LOCALLIBDIR            = '#',
59    LIBPATH                = [ '$LOCALLIBDIR' ],
60    LIBS                   = [ 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
61                               '$BOOSTFSLIB' ], 
62    TEST_EXTRA_LIBS        = [ ],
63
64    PREFIX                 = '/usr/local',
65    LIBINSTALLDIR          = '$PREFIX/lib',
66    BININSTALLDIR          = '$PREFIX/bin',
67    INCLUDEINSTALLDIR      = '$PREFIX/include',
68    OBJINSTALLDIR          = '$LIBINSTALLDIR',
69    DOCINSTALLDIR          = '$PREFIX/doc',
70    CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
71    CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
72
73    # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
74    INLINE_OPTS_DEBUG      = [ '-finline-limit=20000', '-fvisibility-inlines-hidden', 
75                               '-fno-inline-functions', '-Winline' 
76                               '--param','large-function-growth=10000',
77                               '--param', 'large-function-insns=10000', 
78                               '--param','inline-unit-growth=10000' ],
79    INLINE_OPTS_NORMAL     = [ '-finline-limit=5000' ],
80    INLINE_OPTS            = [ '$INLINE_OPTS_NORMAL' ],
81    CXXFLAGS               = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
82                               '$CXXFLAGS_' ],
83    CXXFLAGS_              = BuildTypeOptions('CXXFLAGS'),
84    CXXFLAGS_final         = [ '-O3' ],
85    CXXFLAGS_normal        = [ '-O0', '-g' ],
86    CXXFLAGS_debug         = [ '$CXXFLAGS_normal' ],
87
88    CPPDEFINES             = [ '$expandLogOption', '$CPPDEFINES_' ],
89    expandLogOption        = senfutil.expandLogOption,
90    CPPDEFINES_            = BuildTypeOptions('CPPDEFINES'),
91    CPPDEFINES_final       = [ ],
92    CPPDEFINES_normal      = [ 'SENF_DEBUG' ],
93    CPPDEFINES_debug       = [ '$CPPDEFINES_normal' ],
94
95    LINKFLAGS              = [ '-rdynamic', '$LINKFLAGS_' ],
96    LINKFLAGS_             = BuildTypeOptions('LINKFLAGS'),
97    LINKFLAGS_final        = [ ],
98    LINKFLAGS_normal       = [ '-Wl,-S' ],
99    LINKFLAGS_debug        = [ ],
100 )
101
102 env.SetDefault(
103     LIBSENF = "senf",
104     final   = 0,
105     debug   = 0,
106 )
107
108 # Set variables from command line
109 env.Replace(**ARGUMENTS)
110
111 Export('env')
112
113 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
114 # Create it even when cleaning, to silence the doxygen builder warnings
115 if not os.path.exists("Doxyfile.local"):
116     Execute(Touch("Doxyfile.local"))
117
118 # Create local_config.h
119 if not env.GetOption('clean') and not os.path.exists("local_config.hh"):
120     Execute(Touch("local_config.hh"))
121
122 ###########################################################################
123 # Define build targets
124
125 # Before defining any targets, check wether this is the first build in
126 # pristine directory tree. If so, call 'scons prepare' so the dependencies
127 # created later are correct (yes, this is a hack :-( )
128
129 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
130    and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
131     env.Execute([ "scons prepare" ])
132 env.Clean('all', '.prepare-stamp')
133
134 # Load SConscripts. Need to load some first (they change the global environment)
135 initSConscripts = [ 
136     "debian/SConscript",
137     "doclib/SConscript",
138 ]
139
140 SConscript(initSConscripts)
141
142 if os.path.exists('SConscript.local'):
143     SConscript('SConscript.local')
144
145 SConscript(list(set(glob.glob("*/SConscript")) - set(initSConscripts)))
146
147 # Define the main targets
148 SENFSCons.StandardTargets(env)
149 SENFSCons.GlobalTargets(env)
150
151 env.Depends( SENFSCons.Doxygen(env), env.Value(env['ENV']['REVISION']) )
152
153 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
154 env.Default(libsenf)
155 env.Clean('all', libsenf)
156 env.Alias('default', libsenf)
157
158 SENFSCons.InstallIncludeFiles(env, [ 'config.hh' ])
159 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
160
161 if env.GetOption('clean'):
162     env.Clean('all', [ os.path.join(path,f)
163                        for path, subdirs, files in os.walk('.')
164                        for pattern in env['CLEAN_PATTERNS']
165                        for f in fnmatch.filter(files,pattern) ])
166
167 SENFSCons.PhonyTarget(env, 'prepare', [ 'true' ])
168
169 SENFSCons.PhonyTarget(env, 'valgrind', [ """
170     find -name .test.bin 
171         | while read test; do
172             echo;
173             echo "Running $$test";
174             echo;
175             valgrind --tool=memcheck --error-exitcode=99 --suppressions=valgrind.sup 
176                 $$test $BOOSTTESTARGS;
177             [ $$? -ne 99 ] || exit 1;
178         done
179 """.replace("\n"," ") ], [ 'all_tests' ])
180
181 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
182     Execute(Touch(".prepare-stamp"))