Replace SENFSCons.InstallIncludeFiles with InstallSubdir builder calls
[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('CompileCheck', [ 'senfscons' ])
19 env.Tool('Boost', [ 'senfscons' ])
20 env.Tool('BoostUnitTests', [ 'senfscons' ])
21 env.Tool('InstallSubdir', [ 'senfscons' ])
22
23 env.Help("""
24 Additional top-level build targets:
25
26 prepare      Create all target 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 class BuildTypeOptions:
40     def __init__(self, var):
41         self._var = var
42
43     def __call__(self, target, source, env, for_signature):
44         type = env['final'] and "final" or env['debug'] and "debug" or "normal"
45         return env[self._var + "_" + type]
46
47 env.Append(
48    ENV                    = { 'PATH' : os.environ.get('PATH') },
49    CLEAN_PATTERNS         = [ '*~', '#*#', '*.pyc', 'semantic.cache', '.sconsign*', '.sconsign' ],
50
51    CPPPATH                = [ '#/include' ],
52    LOCALLIBDIR            = '#',
53    LIBPATH                = [ '$LOCALLIBDIR' ],
54    LIBS                   = [ 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB',
55                               '$BOOSTFSLIB' ], 
56    TEST_EXTRA_LIBS        = [ ],
57
58    PREFIX                 = '/usr/local',
59    LIBINSTALLDIR          = '$PREFIX/lib',
60    BININSTALLDIR          = '$PREFIX/bin',
61    INCLUDEINSTALLDIR      = '$PREFIX/include',
62    OBJINSTALLDIR          = '$LIBINSTALLDIR',
63    DOCINSTALLDIR          = '$PREFIX/doc',
64    CPP_INCLUDE_EXTENSIONS = [ '.h', '.hh', '.ih', '.mpp', '.cci', '.ct', '.cti' ],
65    CPP_EXCLUDE_EXTENSIONS = [ '.test.hh' ],
66
67    # These options are insane. Only useful for inline debugging. Need at least 1G free RAM
68    INLINE_OPTS_DEBUG      = [ '-finline-limit=20000', '-fvisibility-inlines-hidden', 
69                               '-fno-inline-functions', '-Winline' 
70                               '--param','large-function-growth=10000',
71                               '--param', 'large-function-insns=10000', 
72                               '--param','inline-unit-growth=10000' ],
73    INLINE_OPTS_NORMAL     = [ '-finline-limit=5000' ],
74    INLINE_OPTS            = [ '$INLINE_OPTS_NORMAL' ],
75    CXXFLAGS               = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', '$INLINE_OPTS',
76                               '$CXXFLAGS_' ],
77    CXXFLAGS_              = BuildTypeOptions('CXXFLAGS'),
78    CXXFLAGS_final         = [ '-O3' ],
79    CXXFLAGS_normal        = [ '-O0', '-g' ],
80    CXXFLAGS_debug         = [ '$CXXFLAGS_normal' ],
81
82    CPPDEFINES             = [ '$expandLogOption', '$CPPDEFINES_' ],
83    expandLogOption        = senfutil.expandLogOption,
84    CPPDEFINES_            = BuildTypeOptions('CPPDEFINES'),
85    CPPDEFINES_final       = [ ],
86    CPPDEFINES_normal      = [ 'SENF_DEBUG' ],
87    CPPDEFINES_debug       = [ '$CPPDEFINES_normal' ],
88
89    LINKFLAGS              = [ '-rdynamic', '$LINKFLAGS_' ],
90    LINKFLAGS_             = BuildTypeOptions('LINKFLAGS'),
91    LINKFLAGS_final        = [ ],
92    LINKFLAGS_normal       = [ '-Wl,-S' ],
93    LINKFLAGS_debug        = [ ],
94 )
95
96 env.SetDefault(
97     LIBSENF = "senf",
98     final   = 0,
99     debug   = 0,
100 )
101
102 # Set variables from command line
103 env.Replace(**ARGUMENTS)
104
105 Export('env')
106
107 # Create Doxyfile.local otherwise doxygen will barf on this non-existent file
108 # Create it even when cleaning, to silence the doxygen builder warnings
109 if 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 (yes, this is a hack :-( )
122
123 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \
124    and not os.environ.get("SCONS") and COMMAND_LINE_TARGETS != [ 'prepare' ]:
125     env.Execute([ "scons prepare" ])
126 env.Clean('all', '.prepare-stamp')
127
128 # Load SConscripts. Need to load some first (they change the global environment)
129 initSConscripts = [ 
130     "debian/SConscript",
131     "doclib/SConscript",
132 ]
133
134 SConscript(initSConscripts)
135
136 if os.path.exists('SConscript.local'):
137     SConscript('SConscript.local')
138
139 SConscript(list(set(glob.glob("*/SConscript")) - set(initSConscripts)))
140
141 # Define the main targets
142 env.Alias('all', [ 'default', 'all_tests', 'all_docs' ])
143
144 env.Depends(SENFSCons.Doxygen(env), env.Value(env['ENV']['REVISION']))
145
146 libsenf = env.Library(env.subst("$LIBSENF$LIBADDSUFFIX"), env['ALLOBJECTS'])
147 env.Default(libsenf)
148 env.Clean('all', libsenf)
149 env.Alias('default', libsenf)
150
151 env.InstallSubdir(target = '$INCLUDEINSTALLDIR', source = [ 'config.hh' ])
152
153 env.Alias('install_all', env.Install('$LIBINSTALLDIR', libsenf))
154
155 if env.GetOption('clean'):
156     env.Clean('all', [ os.path.join(path,f)
157                        for path, subdirs, files in os.walk('.')
158                        for pattern in env['CLEAN_PATTERNS']
159                        for f in fnmatch.filter(files,pattern) ])
160
161 SENFSCons.PhonyTarget(env, 'prepare', [ 'true' ])
162
163 SENFSCons.PhonyTarget(env, 'valgrind', [ """
164     find -name .test.bin 
165         | while read test; do
166             echo;
167             echo "Running $$test";
168             echo;
169             valgrind --tool=memcheck --error-exitcode=99 --suppressions=valgrind.sup 
170                 $$test $BOOSTTESTARGS;
171             [ $$? -ne 99 ] || exit 1;
172         done
173 """.replace("\n"," ") ], [ 'all_tests' ])
174
175 if not env.GetOption('clean') and not os.path.exists(".prepare-stamp"):
176     Execute(Touch(".prepare-stamp"))