source: trunk/ithildin/SConstruct @ 797

Revision 797, 10.9 KB checked in by wd, 5 years ago (diff)

Fix dumb variable name typo (which was perfectly typo'd across three
instances?) and sort module names in the config option. Alose use Clone()
and not Copy() per scons 0.96.93 update.

  • Property svn:keywords set to Id Rev
Line 
1# #############################################################################
2# SConstruct: SCons build instructions
3#
4# Copyright 2006 the Ithildin Project.
5# See the COPYING file for more information on licensing and use.
6#
7# $Id$
8#
9# #############################################################################
10
11###############################################################################
12# Initial setup (Python path tweaks etc)
13
14package_name = "ithildin"
15package_version = "1.2.0"
16
17EnsurePythonVersion(2,2)
18EnsureSConsVersion(0,96,92)
19
20import glob, os, sys
21# let's just stick the realpath() for ./build in there at the front.  THis
22# allows us to use our custom test code in the 'tests' module there.
23sys.path.insert(0, os.path.realpath('./build'))
24import tests
25
26###############################################################################
27# Global environment setup.  Import the user's $PATH for our own sanity.
28env = Environment(ENV = {
29    'PATH': os.environ['PATH'],
30    },
31    CPPPATH = ['#/include']
32)
33
34# Perform some magic to get the repository version.  If we have svn and we
35# can use xml.dom.minidom let's go for it
36try:
37    subversion = WhereIs('svn')
38    import xml.dom.minidom
39    if subversion:
40        dom = xml.dom.minidom.parseString(
41            os.popen('%s info --xml .' % subversion).read())
42        e = dom.getElementsByTagName('entry')[0]
43        package_repository_version = int(e.getAttribute('revision'))
44        dom.unlink()
45except:
46    # no luck eh, let's cheat
47    svnrev = "$Rev$"
48    package_repository_version = int(svnrev.split()[1])
49
50# Find our availabe modules
51available_modules = []
52for e in os.listdir('modules'):
53    if os.path.exists('modules/%s/SConscript' % e):
54        available_modules.append(e)
55available_modules.sort()
56
57###############################################################################
58# Options
59
60# Collect the list of modules we have shipped with
61
62if not os.path.exists('build/options'):
63    env.Help("""
64You may save your build options in the file build/options with the format:
65optionname = "optionvalue"
66A sample options file is provided in build/options.default.
67""")
68
69opts = Options('build/options', ARGUMENTS)
70opts.AddOptions(
71    BoolOption('debug', 'Enable creation of debugging symbols', 0),
72    ('fdsetsize', 'Override value of FD_SETSIZE', 0),
73    BoolOption('ipv6', 'Enable IPv6 support', 1),
74    ListOption('modules', 'Modules to build', 'all', available_modules),
75    PackageOption('openssl', 'Enable OpenSSL support', 'yes'),
76    ListOption('poller', 'Socket polling method', 'auto',
77        ['kqueue', 'poll', 'select', 'auto']),
78    BoolOption('warnings', 'Compile with very aggressive warning settings', 0),
79# Other path options are handled below
80    PathOption('prefix', 'Installation prefix', '/usr/local',
81        tests.PathIsDirCreateAccess),
82)
83opts.Update(env)
84
85# Now take a look in prefix for the stuff we care about: bin, etc, lib,
86# include, share.  If these already exist we make our defaults
87# $prefix/etc/ithildin etc.  Otherwise we make them $prefix/etc (assuming
88# this is a lone installation location).  This is an automated version of
89# the old  --disable-dir-suffix autoconf macro from 1.1 and lower.
90#
91# XXX: this is all dumb in Windows where installations will be totally
92# different.
93
94# Okay, let's make some dumb guesses:  If the name already contains
95# 'package' in it let's go ahead and not add that again.  If the name is
96# standard (/usr, /usr/local, /opt) let's add it there.  Other than that we
97# aren't too smart. :)
98if env['prefix'] == '/usr' or env['prefix'] == '/opt':
99    # /usr and /opt need special handling to stuff things in /etc
100    sysconfdir = '/etc'
101else:
102    sysconfdir = env['prefix'] + '/etc'
103
104dir_suffix = ''
105if not package_name in env['prefix']:
106    dir_suffix = '/' + package_name
107# let's add one more, if it's in $HOME/<something> let's guess that they
108# don't want that nasty dir_suffix.  This could be so wrong as to be absurd,
109# but I believe it is what most will want.
110if (os.environ.has_key('HOME') and os.environ['HOME'] in env['prefix']):
111    dir_suffix = ''
112
113opts.AddOptions(
114    PathOption('bindir', "Binary installation directory",
115        env['prefix'] + '/bin', tests.PathIsDirCreateAccess),
116    PathOption('sysconfdir', "Configuration file installation directory",
117        sysconfdir + dir_suffix, tests.PathIsDirCreateAccess),
118    PathOption('libdir', "Library installation directory",
119        env['prefix'] + '/lib' + dir_suffix, tests.PathIsDirCreateAccess),
120    PathOption('includedir', 'C header installation directory',
121        env['prefix'] + '/include', tests.PathIsDirCreateAccess),
122    PathOption('datadir', "Miscellaneous file installation directory",
123        env['prefix'] + '/share' + dir_suffix, tests.PathIsDirCreateAccess),
124)
125opts.Update(env)
126
127env.Help(opts.GenerateHelpText(env))
128
129###############################################################################
130# Feature tests
131
132conf = env.Configure(config_h = 'include/ithildin/config.h',
133    custom_tests = tests.tests)
134
135conf.CheckCCompiler()
136conf.CheckCVersion()
137
138# header tests:
139# We have headers we want, headers we need, and we save all this to a final
140# variable listing all the headers we have.
141need_headers = Split('''
142assert.h errno.h limits.h math.h stdbool.h string.h
143''')
144want_headers = Split('''
145dl.h dlfcn.h fcntl.h features.h grp.h netdb.h pwd.h strings.h time.h unistd.h
146arpa/inet.h
147machine/endian.h
148netinet/in.h
149sys/mman.h sys/resource.h sys/socket.h sys/stat.h sys/time.h
150
151windows.h winsock.h
152''')
153
154have_headers = list()
155for h in want_headers:
156    if conf.CheckHeader(h): have_headers.append(h)
157for h in need_headers:
158    if conf.CheckHeader(h): have_headers.append(h)
159    else:
160        print 'Header %s is required for compilation' % h
161        env.Exit(1)
162
163# library tests:
164# Somewhat different, we use the want/need lists but they are a list of
165# tuples (library name and function to check for).  The have list remains a
166# list of libs we have
167
168want_libs = [
169('dl', 'dlopen'),
170('nsl', 'gethostbyname'),
171('socket', 'socket'),
172]
173need_libs = list()
174have_libs = list()
175
176for l in want_libs:
177    if conf.CheckLib(library = l[0], symbol = l[1]): have_libs.append(l[0])
178for l in need_libs:
179    if conf.CheckLib(library = l[0], symbol = l[1]): have_libs.append(l[0])
180    else:
181        print 'Library %s is required for compilation' % l[0]
182        env.Exit(1)
183
184# function tests:
185# Here again we have functions we need, functioncs we want, and a final
186# listing of functions we have
187want_funcs = Split('''
188getaddrinfo kqueue poll select
189fmtcheck strlcat strlcpy strsep
190getegid getgid getgrnam setegid setgid setgroups
191geteuid getuid getpwnam seteuid setuid
192readlink getenv recv send setsockopt
193getrlimit setrlimit
194''')
195# XXX: fill in need_funcs with a reasonable subset of what we need, stuff
196# that will prove various libraries exist.  Blech!
197need_funcs = list()
198
199have_funcs = list()
200
201for f in want_funcs:
202    if conf.CheckFunc(f): have_funcs.append(f)
203for f in need_funcs:
204    if conf.CheckFunc(f): have_funcs.append(f)
205    else:
206        print 'Function %s is required for compilation' % f
207        env.Exit(1)
208
209# OpenSSL test:
210# We need libs and headers above first, in some cases, to test this.
211if env['openssl']:
212    # if the configured option is not an integer it must be their desired
213    # path(s)
214    if env['openssl'].__class__ is not int:
215        res = conf.CheckOpenSSL(Split(env['openssl']))
216    else:
217        res = conf.CheckOpenSSL()
218
219    if not res:
220        print 'Could not find OpenSSL.  If you wish to build without support'
221        print 'for SSL please specify openssl=no to the build command'
222        Exit(1)
223
224    env.Append(CPPDEFINES = ['HAVE_OPENSSL'])
225
226# IPv6 test:
227# We just look to see if we have getaddrinfo and if they want IPv6 support
228if conf.CheckIPv6(have_funcs):
229    env.Append(CPPDEFINES = ['INET6'])
230
231# FD_SETSIZE test:
232# Just check the passed value and decide whether or not to use this
233if env['fdsetsize']:
234    env.Append(CPPDEFINES = ['FD_SETSIZE=%s'] % env['fdsetsize'])
235
236# Poller selection:
237# If they ask for auto go in the preference order of: kqueue > poll > select
238# except when Linux is provided, in which case we always use select() (weird
239# breakage with poll() on Linux and it has no kqueue).  If they ask for
240# something explicit we'll always use that.
241kqueue_supported_on = ['DragonFlyBSD', 'FreeBSD', 'NetBSD', 'OpenBSD']
242host_os = os.uname()[0]
243if str(env['poller']) == 'auto':
244    if host_os == 'Linux':
245        env['poller'] = 'select'
246    elif 'kqueue' in have_funcs and host_os in kqueue_supported_on:
247        env['poller'] = 'kqueue'
248    elif 'poll' in have_funcs:
249        env['poller'] = 'poll'
250    elif 'select' in have_funcs:
251        env['poller'] = 'select'
252    else:
253        print 'Unable to find suitable polling function'
254        Exit(1)
255
256# now take the poller value, set for correctness, and double check it
257if not str(env['poller']) in have_funcs:
258    print 'We do not have the %s poller' % env['poller']
259    Exit(1)
260
261env.Append(CPPDEFINES = ['POLLER_%s' % str(env['poller']).upper()])
262
263# And let's set compiler options!
264if env['CC'] == 'gcc':
265    if env['debug']:
266        env.AppendUnique(CCFLAGS = ['-O', '-g3'])
267    if env['warnings']:
268        env.AppendUnique(CCFLAGS = Split('''
269            -Wall -Wshadow -Wmissing-declarations -Wpointer-arith
270            -Wcast-align -Wstrict-prototypes -Wmissing-prototypes
271            -Wmissing-declarations -Wredundant-decls -Winline
272            -Wbad-function-cast
273            '''))
274
275conf.Finish()
276
277# leave this here for debugging (just comment it out...)
278#print env.Dictionary()
279
280###############################################################################
281# Build options and subsidiary code
282
283# Set our final environment parameters.
284env.Append(LIBPATH = '#/lib')
285env.AppendUnique(RPATH = [env['libdir'], env['libdir'] + '/modules'])
286
287# Update target for subversion users.
288if subversion:
289    env.AlwaysBuild(env.Alias('update', '#/.svn', '%s update' % subversion))
290# Installation targets for documentation, config and include files
291tests.AddConfInstall(env, env['sysconfdir'], ['etc/ithildin.conf'])
292env.Install(env['datadir'], ['COPYING', 'DEVELOPERS', 'README'])
293env.Install(env['datadir'] + '/doc', glob.glob('doc/*.txt'))
294env.Install(env['includedir'] + '/ithildin',
295    glob.glob('include/ithildin/*.h'))
296
297# dummy install target with our various prefixes.
298env.Alias('install', [env['bindir'], env['sysconfdir'],
299        env['libdir'], env['includedir'], env['datadir']])
300
301# Now export useful variables
302env.Export(['env', 'package_name', 'package_version',
303    'package_repository_version', 'tests'])
304
305# and call our sub-scripts.
306env.SConscript('lib/SConscript')
307env.SConscript('source/SConscript')
308
309# Add the requested modules too!
310if str(env['modules']) == 'all':
311    modules = str.join(',', available_modules)
312elif str(env['modules']) == 'none':
313    modules = ''
314else:
315    modules = str(env['modules'])
316
317for m in modules.split(','):
318    if not m: continue
319    # create a modified env for each module
320    modenv = env.Clone()
321    env.SConscript('modules/%s/SConscript' % m, exports = ['modenv'])
322    del modenv
323
324# vi:set ts=8 sts=4 sw=4 tw=76 et syntax=python:
Note: See TracBrowser for help on using the repository browser.