[scons] add some generic defintions early
[lighttpd.git] / SConstruct
blob4c7732d388d1f34593f915bc517ce6445c784e49
1 import os
2 import re
3 import string
4 import sys
5 from copy import copy
6 from stat import *
8 package = 'lighttpd'
9 version = '1.4.48'
11 def fail(*args, **kwargs):
12 print(*args, file=sys.stderr, **kwargs)
13 env.Exit(-1)
15 def checkCHeaders(autoconf, hdrs):
16 p = re.compile('[^A-Z0-9]')
17 for hdr in hdrs:
18 if not hdr:
19 continue
20 _hdr = Split(hdr)
21 if autoconf.CheckCHeader(_hdr):
22 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', _hdr[-1].upper()) ])
24 def checkFunc(autoconf, func, header):
25 p = re.compile('[^A-Z0-9]')
26 if autoconf.CheckFunc(func, header):
27 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', func.upper()) ])
29 def checkFuncs(autoconf, funcs):
30 p = re.compile('[^A-Z0-9]')
31 for func in funcs:
32 if autoconf.CheckFunc(func):
33 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', func.upper()) ])
35 def checkTypes(autoconf, types):
36 p = re.compile('[^A-Z0-9]')
37 for type in types:
38 if autoconf.CheckType(type, '#include <sys/types.h>'):
39 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', type.upper()) ])
41 def checkGmtOffInStructTm(context):
42 source = """
43 #include <time.h>
44 int main() {
45 struct tm a;
46 a.tm_gmtoff = 0;
47 return 0;
49 """
50 context.Message('Checking for tm_gmtoff in struct tm...')
51 result = context.TryLink(source, '.c')
52 context.Result(result)
54 return result
56 def checkIPv6(context):
57 source = """
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <netinet/in.h>
62 int main() {
63 struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0;
64 return 0;
66 """
67 context.Message('Checking for IPv6 support...')
68 result = context.TryLink(source, '.c')
69 context.Result(result)
71 return result
73 def checkWeakSymbols(context):
74 source = """
75 __attribute__((weak)) void __dummy(void *x) { }
76 int main() {
77 void *x;
78 __dummy(x);
80 """
81 context.Message('Checking for weak symbol support...')
82 result = context.TryLink(source, '.c')
83 context.Result(result)
85 return result
87 def checkProgram(env, withname, progname):
88 withname = 'with_' + withname
89 binpath = None
91 if env[withname] != 1:
92 binpath = env[withname]
93 else:
94 prog = env.Detect(progname)
95 if prog:
96 binpath = env.WhereIs(prog)
98 if binpath:
99 mode = os.stat(binpath)[ST_MODE]
100 if S_ISDIR(mode):
101 fail("* error: path `%s' is a directory" % (binpath))
102 if not S_ISREG(mode):
103 fail("* error: path `%s' is not a file or not exists" % (binpath))
105 if not binpath:
106 fail("* error: can't find program `%s'" % (progname))
108 return binpath
110 VariantDir('sconsbuild/build', 'src', duplicate = 0)
111 VariantDir('sconsbuild/tests', 'tests', duplicate = 0)
113 vars = Variables()
114 vars.AddVariables(
115 ('prefix', 'prefix', '/usr/local'),
116 ('bindir', 'binary directory', '${prefix}/bin'),
117 ('sbindir', 'binary directory', '${prefix}/sbin'),
118 ('libdir', 'library directory', '${prefix}/lib'),
119 PathVariable('CC', 'path to the c-compiler', None),
120 BoolVariable('build_dynamic', 'enable dynamic build', 'yes'),
121 BoolVariable('build_static', 'enable static build', 'no'),
122 BoolVariable('build_fullstatic', 'enable fullstatic build', 'no'),
124 BoolVariable('with_bzip2', 'enable bzip2 compression', 'no'),
125 PackageVariable('with_dbi', 'enable dbi support', 'no'),
126 BoolVariable('with_fam', 'enable FAM/gamin support', 'no'),
127 BoolVariable('with_gdbm', 'enable gdbm support', 'no'),
128 BoolVariable('with_geoip', 'enable GeoIP support', 'no'),
129 BoolVariable('with_krb5', 'enable krb5 auth support', 'no'),
130 BoolVariable('with_ldap', 'enable ldap auth support', 'no'),
131 # with_libev not supported
132 # with_libunwind not supported
133 BoolVariable('with_lua', 'enable lua support for mod_cml', 'no'),
134 BoolVariable('with_memcached', 'enable memcached support', 'no'),
135 PackageVariable('with_mysql', 'enable mysql support', 'no'),
136 BoolVariable('with_openssl', 'enable openssl support', 'no'),
137 PackageVariable('with_pcre', 'enable pcre support', 'yes'),
138 PackageVariable('with_pgsql', 'enable pgsql support', 'no'),
139 BoolVariable('with_sqlite3', 'enable sqlite3 support (required for webdav props)', 'no'),
140 BoolVariable('with_uuid', 'enable uuid support (required for webdav locks)', 'no'),
141 # with_valgrind not supported
142 # with_xattr not supported
143 PackageVariable('with_xml', 'enable xml support (required for webdav props)', 'no'),
144 BoolVariable('with_zlib', 'enable deflate/gzip compression', 'no'),
146 BoolVariable('with_all', 'enable all with_* features', 'no'),
149 env = Environment(
150 ENV = os.environ,
151 variables = vars,
152 CPPPATH = Split('#sconsbuild/build')
155 env.Help(vars.GenerateHelpText(env))
157 if env.subst('${CC}') is not '':
158 env['CC'] = env.subst('${CC}')
160 env['package'] = package
161 env['version'] = version
162 if env['CC'] == 'gcc':
163 ## we need x-open 6 and bsd 4.3 features
164 env.Append(CCFLAGS = Split('-Wall -O2 -g -W -pedantic -Wunused -Wshadow -std=gnu99'))
166 env.Append(CPPFLAGS = [
167 '-D_FILE_OFFSET_BITS=64',
168 '-D_LARGEFILE_SOURCE',
169 '-D_LARGE_FILES',
170 '-D_GNU_SOURCE',
173 if env['with_all']:
174 for feature in vars.keys():
175 # only enable 'with_*' flags
176 if not feature.startswith('with_'): continue
177 # don't overwrite manual arguments
178 if feature in vars.args: continue
179 # now activate
180 env[feature] = True
182 # cache configure checks
183 if 1:
184 autoconf = Configure(env, custom_tests = {
185 'CheckGmtOffInStructTm': checkGmtOffInStructTm,
186 'CheckIPv6': checkIPv6,
187 'CheckWeakSymbols': checkWeakSymbols,
190 if 'CFLAGS' in os.environ:
191 autoconf.env.Append(CCFLAGS = os.environ['CFLAGS'])
192 print(">> Appending custom build flags : " + os.environ['CFLAGS'])
194 if 'LDFLAGS' in os.environ:
195 autoconf.env.Append(LINKFLAGS = os.environ['LDFLAGS'])
196 print(">> Appending custom link flags : " + os.environ['LDFLAGS'])
198 if 'LIBS' in os.environ:
199 autoconf.env.Append(APPEND_LIBS = os.environ['LIBS'])
200 print(">> Appending custom libraries : " + os.environ['LIBS'])
201 else:
202 autoconf.env.Append(APPEND_LIBS = '')
204 autoconf.headerfile = "foo.h"
205 checkCHeaders(autoconf, string.split("""
206 arpa/inet.h
207 crypt.h
208 fcntl.h
209 getopt.h
210 inttypes.h
211 linux/random.h
212 netinet/in.h
213 poll.h
214 pwd.h
215 stdint.h
216 stdlib.h
217 string.h
218 strings.h
219 sys/devpoll.h
220 sys/epoll.h
221 sys/event.h
222 sys/filio.h
223 sys/mman.h
224 sys/poll.h
225 sys/port.h
226 sys/prctl.h
227 sys/resource.h
228 sys/select.h
229 sys/sendfile.h
230 sys/socket.h
231 sys/time.h
232 sys/time.h sys/types.h sys/resource.h
233 sys/types.h netinet/in.h
234 sys/types.h sys/event.h
235 sys/types.h sys/mman.h
236 sys/types.h sys/select.h
237 sys/types.h sys/socket.h
238 sys/types.h sys/uio.h
239 sys/types.h sys/un.h
240 sys/uio.h
241 sys/un.h
242 sys/wait.h
243 syslog.h
244 unistd.h
245 winsock2.h""", "\n"))
247 checkFuncs(autoconf, Split('fork stat lstat strftime dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
248 strdup strerror strstr strtol sendfile getopt socket \
249 gethostbyname poll epoll_ctl getrlimit chroot \
250 getuid select signal pathconf madvise prctl\
251 writev sigaction sendfile64 send_file kqueue port_create localtime_r posix_fadvise issetugid inet_pton \
252 memset_s explicit_bzero clock_gettime pipe2 \
253 arc4random_buf jrand48 srandom getloadavg'))
254 checkFunc(autoconf, 'getentropy', 'sys/random.h')
255 checkFunc(autoconf, 'getrandom', 'linux/random.h')
257 checkTypes(autoconf, Split('pid_t size_t off_t'))
259 autoconf.env.Append( LIBSQLITE3 = '', LIBXML2 = '', LIBMYSQL = '', LIBZ = '',
260 LIBPGSQL = '', LIBDBI = '',
261 LIBBZ2 = '', LIBCRYPT = '', LIBMEMCACHED = '', LIBFCGI = '', LIBPCRE = '',
262 LIBLDAP = '', LIBLBER = '', LIBLUA = '', LIBDL = '', LIBUUID = '',
263 LIBKRB5 = '', LIBGSSAPI_KRB5 = '', LIBGDBM = '', LIBSSL = '', LIBCRYPTO = '')
265 # have crypt_r/crypt, and is -lcrypt needed?
266 if autoconf.CheckLib('crypt', autoadd = 0):
267 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LIBCRYPT' ], LIBCRYPT = 'crypt')
268 oldlib = env['LIBS']
269 env['LIBS'] = ['crypt']
270 checkFuncs(autoconf, ['crypt', 'crypt_r'])
271 env['LIBS'] = oldlib
272 else:
273 checkFuncs(autoconf, ['crypt', 'crypt_r'])
275 if autoconf.CheckType('socklen_t', '#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/types.h>'):
276 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_SOCKLEN_T' ])
278 if autoconf.CheckType('struct sockaddr_storage', '#include <sys/socket.h>\n'):
279 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_STRUCT_SOCKADDR_STORAGE' ])
281 if autoconf.CheckLibWithHeader('rt', 'time.h', 'c', 'clock_gettime(CLOCK_MONOTONIC, (struct timespec*)0);', autoadd = 0):
282 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_CLOCK_GETTIME' ], LIBS = [ 'rt' ])
284 if autoconf.CheckIPv6():
285 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_IPV6' ])
287 if autoconf.CheckWeakSymbols():
288 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_WEAK_SYMBOLS' ])
290 if autoconf.CheckGmtOffInStructTm():
291 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_STRUCT_TM_GMTOFF' ])
293 if autoconf.CheckLibWithHeader('dl', 'dlfcn.h', 'C', autoadd = 0):
294 autoconf.env.Append(LIBDL = 'dl')
296 # used in tests if present
297 if autoconf.CheckLibWithHeader('fcgi', 'fastcgi.h', 'C', autoadd = 0):
298 autoconf.env.Append(LIBFCGI = 'fcgi')
300 if env['with_bzip2']:
301 if not autoconf.CheckLibWithHeader('bz2', 'bzlib.h', 'C', autoadd = 0):
302 fail("Couldn't find bz2")
303 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_BZLIB_H', '-DHAVE_LIBBZ2' ], LIBBZ2 = 'bz2')
305 if env['with_dbi']:
306 if not autoconf.CheckLibWithHeader('dbi', 'dbi/dbi.h', 'C', autoadd = 0):
307 fail("Couldn't find dbi")
308 env.Append(CPPFLAGS = [ '-DHAVE_DBI_H', '-DHAVE_LIBDBI' ], LIBDBI = 'dbi')
310 if env['with_fam']:
311 if not autoconf.CheckLibWithHeader('fam', 'fam.h', 'C', autoadd = 0):
312 fail("Couldn't find fam")
313 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_FAM_H', '-DHAVE_LIBFAM' ], LIBS = [ 'fam' ])
314 checkFuncs(autoconf, ['FAMNoExists']);
316 if env['with_gdbm']:
317 if not autoconf.CheckLibWithHeader('gdbm', 'gdbm.h', 'C', autoadd = 0):
318 fail("Couldn't find gdbm")
319 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_GDBM_H', '-DHAVE_GDBM' ], LIBGDBM = 'gdbm')
321 if env['with_geoip']:
322 if not autoconf.CheckLibWithHeader('GeoIP', 'GeoIP.h', 'C', autoadd = 0):
323 fail("Couldn't find geoip")
324 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_GEOIP' ], LIBGEOIP = 'GeoIP')
326 if env['with_krb5']:
327 if not autoconf.CheckLibWithHeader('krb5', 'krb5.h', 'C', autoadd = 0):
328 fail("Couldn't find krb5")
329 if not autoconf.CheckLibWithHeader('gssapi_krb5', 'gssapi/gssapi_krb5.h', 'C', autoadd = 0):
330 fail("Couldn't find gssapi_krb5")
331 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_KRB5' ], LIBKRB5 = 'krb5')
332 autoconf.env.Append(LIBGSSAPI_KRB5 = 'gssapi_krb5')
334 if env['with_ldap']:
335 if not autoconf.CheckLibWithHeader('ldap', 'ldap.h', 'C', autoadd = 0):
336 fail("Couldn't find ldap")
337 if not autoconf.CheckLibWithHeader('lber', 'lber.h', 'C', autoadd = 0):
338 fail("Couldn't find lber")
339 autoconf.env.Append(CPPFLAGS = [ '-DLDAP_DEPRECATED=1' ])
340 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LDAP_H', '-DHAVE_LIBLDAP' ], LIBLDAP = 'ldap')
341 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LBER_H', '-DHAVE_LIBLBER' ], LIBLBER = 'lber')
343 if env['with_lua']:
344 def TryLua(env, name):
345 result = False
346 oldlibs = copy(env['LIBS'])
347 try:
348 print("Searching for lua: " + name + " >= 5.0")
349 env.ParseConfig("pkg-config '" + name + " >= 5.0' --cflags --libs")
350 env.Append(LIBLUA = env['LIBS'][len(oldlibs):])
351 env.Append(CPPFLAGS = [ '-DHAVE_LUA_H' ])
352 result = True
353 except:
354 pass
355 env['LIBS'] = oldlibs
356 return result
358 found_lua = False
359 for lua_name in ['lua5.3', 'lua-5.3', 'lua5.2', 'lua-5.2', 'lua5.1', 'lua-5.1', 'lua']:
360 if TryLua(env, lua_name):
361 found_lua = True
362 break
363 if not found_lua:
364 fail("Couldn't find any lua implementation")
366 if env['with_memcached']:
367 if not autoconf.CheckLibWithHeader('memcached', 'libmemcached/memcached.h', 'C', autoadd = 0):
368 fail("Couldn't find memcached")
369 autoconf.env.Append(CPPFLAGS = [ '-DUSE_MEMCACHED' ], LIBMEMCACHED = 'memcached')
371 if env['with_mysql']:
372 mysql_config = checkProgram(env, 'mysql', 'mysql_config')
373 oldlib = env['LIBS']
374 env['LIBS'] = []
375 env.ParseConfig(mysql_config + ' --cflags --libs')
376 env.Append(CPPFLAGS = [ '-DHAVE_MYSQL_H', '-DHAVE_LIBMYSQL' ], LIBMYSQL = 'mysqlclient')
377 env['LIBS'] = oldlib
379 if env['with_openssl']:
380 if not autoconf.CheckLibWithHeader('ssl', 'openssl/ssl.h', 'C', autoadd = 0):
381 fail("Couldn't find openssl")
382 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_OPENSSL_SSL_H', '-DHAVE_LIBSSL'] , LIBSSL = 'ssl', LIBCRYPTO = 'crypto')
384 if env['with_pcre']:
385 pcre_config = checkProgram(env, 'pcre', 'pcre-config')
386 oldlib = env['LIBS']
387 env['LIBS'] = []
388 env.ParseConfig(pcre_config + ' --cflags --libs')
389 env.Append(CPPFLAGS = [ '-DHAVE_PCRE_H', '-DHAVE_LIBPCRE' ], LIBPCRE = env['LIBS'])
390 env['LIBS'] = oldlib
392 if env['with_pgsql']:
393 oldlib = env['LIBS']
394 env['LIBS'] = []
395 env.ParseConfig('pkg-config libpq --cflags --libs')
396 env.Append(CPPFLAGS = [ '-DHAVE_PGSQL_H', '-DHAVE_LIBPGSQL' ], LIBPGSQL = 'pq')
397 env['LIBS'] = oldlib
399 if env['with_sqlite3']:
400 if not autoconf.CheckLibWithHeader('sqlite3', 'sqlite3.h', 'C', autoadd = 0):
401 fail("Couldn't find sqlite3")
402 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_SQLITE3_H', '-DHAVE_LIBSQLITE3' ], LIBSQLITE3 = 'sqlite3')
404 if env['with_uuid']:
405 if not autoconf.CheckLibWithHeader('uuid', 'uuid/uuid.h', 'C', autoadd = 0):
406 fail("Couldn't find uuid")
407 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_UUID_UUID_H', '-DHAVE_LIBUUID' ], LIBUUID = 'uuid')
409 if env['with_xml']:
410 xml2_config = checkProgram(env, 'xml', 'xml2-config')
411 oldlib = env['LIBS']
412 env['LIBS'] = []
413 env.ParseConfig(xml2_config + ' --cflags --libs')
414 env.Append(CPPFLAGS = [ '-DHAVE_LIBXML_H', '-DHAVE_LIBXML2' ], LIBXML2 = env['LIBS'])
415 env['LIBS'] = oldlib
417 if env['with_zlib']:
418 if not autoconf.CheckLibWithHeader('z', 'zlib.h', 'C', autoadd = 0):
419 fail("Couldn't find zlib")
420 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_ZLIB_H', '-DHAVE_LIBZ' ], LIBZ = 'z')
422 env = autoconf.Finish()
424 if re.compile("cygwin|mingw|midipix").search(env['PLATFORM']):
425 env.Append(COMMON_LIB = 'bin')
426 elif re.compile("darwin|aix").search(env['PLATFORM']):
427 env.Append(COMMON_LIB = 'lib')
428 else:
429 env.Append(COMMON_LIB = False)
431 versions = string.split(version, '.')
432 version_id = int(versions[0]) << 16 | int(versions[1]) << 8 | int(versions[2])
433 env.Append(CPPFLAGS = [
434 '-DLIGHTTPD_VERSION_ID=' + hex(version_id),
435 '-DPACKAGE_NAME=\\"' + package + '\\"',
436 '-DPACKAGE_VERSION=\\"' + version + '\\"',
437 '-DLIBRARY_DIR="\\"${libdir}\\""',
440 SConscript('src/SConscript', exports = 'env', variant_dir = 'sconsbuild/build', duplicate = 0)
441 SConscript('tests/SConscript', exports = 'env', variant_dir = 'sconsbuild/tests')