loaders: JPG: Fix bussy loop on corrupted file.
[gfxprim.git] / configure
bloba01830e050d8e113e8474e197091aa7a5195d266
1 #!/usr/bin/env python
3 # This is simple script to detect libraries and configure standard features.
5 import os
6 import sys
7 from optparse import OptionParser
8 import subprocess
10 def header_exists(cfg, *filenames):
11 for filename in filenames:
12 fpath = cfg['include_path'][0] + '/' + filename
14 sys.stderr.write("Checking for '%s' ... " % fpath)
16 try:
17 st = os.stat(fpath)
18 sys.stderr.write("Yes\n")
19 return True
20 except os.error:
21 sys.stderr.write("No\n")
22 return False
24 def c_try_compile(cfg, code, msg):
25 sys.stderr.write(msg)
27 ret = os.system("echo '%s' | %s %s -x c -o /dev/null - > /dev/null 2>&1" %
28 (code, cfg['CC'][0], cfg['CFLAGS'][0]))
30 if ret:
31 sys.stderr.write("No\n")
32 return False
33 else:
34 sys.stderr.write("Yes\n")
35 return True
37 def c_compiler_exists(cfg):
38 return c_try_compile(cfg, "int main(void) { return 0; }",
39 "Checking for working compiler (%s) ... " %
40 cfg["CC"][0])
42 def define_fortify_source(cfg):
43 return c_try_compile(cfg, "int main(void) {\n" +
44 "#if !defined _FORTIFY_SOURCE &&" +
45 "defined __OPTIMIZE__ && __OPTIMIZE__\n" +
46 " return 0;\n" +
47 "#else\n" +
48 " #error FORTIFY_SOURCE not usable\n" +
49 "#endif\n" +
50 "}", "Whether to define _FORTIFY_SOURCE ... ");
52 def python_version(cfg):
53 sys.stderr.write("Checking for python-config Python version ... ")
55 if (cfg['PYTHON_CONFIG'][0] is ''):
56 sys.stderr.write('NA\n')
57 return ''
59 cmd = subprocess.Popen([cfg['PYTHON_CONFIG'][0], '--ldflags'],
60 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
61 res = str(cmd.communicate())
62 res = res[res.find('-lpython')+8:]
63 res = res[:3]
65 sys.stderr.write("%s\n" % res)
66 return res
68 def check_for_swig(cfg):
69 sys.stderr.write("Checking for working swig ... ")
71 ret = os.system("%s -version > /dev/null 2>&1" % cfg['SWIG'][0])
73 if ret:
74 sys.stderr.write('No\n')
75 cfg['SWIG'][0] = ''
76 else:
77 sys.stderr.write('Yes\n')
79 def check_for_python_config(cfg):
80 sys.stderr.write("Checking for python-config ... ")
82 ret = os.system("%s --libs > /dev/null 2>&1" % cfg['PYTHON_CONFIG'][0])
84 if ret:
85 sys.stderr.write('No\n')
86 cfg['PYTHON_CONFIG'][0] = ''
87 else:
88 sys.stderr.write('Yes\n')
91 # Adds prefix to *dir vars but only if the path does not start with '/'
93 def cfg_get_value(cfg_key):
94 if (cfg_key.endswith('dir')):
95 value = cfg[cfg_key][0]
96 if (value.startswith('/')):
97 return value
98 else:
99 prefix = cfg['prefix'][0]
100 if (prefix.endswith('/')):
101 return prefix + value
102 else:
103 return prefix + '/' + value
104 else:
105 return cfg[cfg_key][0]
108 # Library checking api
110 class libraries:
111 def __init__(self, libraries, cfg):
112 self.libraries = libraries
113 self.cfg = cfg;
114 # Create dictionary for check results
115 self.results = dict()
117 # Print summary
119 def print_summary(self):
120 sys.stderr.write("Settings and variables\n")
121 sys.stderr.write("----------------------\n")
123 for i in cfg:
124 value = cfg_get_value(i)
125 sys.stderr.write("%14s : '%s'\n" % (i, value))
126 sys.stderr.write(" - %s\n\n" % cfg[i][1])
128 sys.stderr.write("Libraries to link against\n")
129 sys.stderr.write("-------------------------\n")
131 for i in self.libraries:
132 sys.stderr.write("%10s" % i[0])
134 if (self.results[i[0]]):
135 sys.stderr.write(" : Enabled\n")
136 else:
137 sys.stderr.write(" : Disabled\n")
139 sys.stderr.write(" - %s\n\n" % i[1])
141 # Enable/Disable library
143 def set(self, name, val):
144 if name not in map(lambda s: s[0], self.libraries):
145 sys.stderr.write("ERROR: Invalid library '%s'\n" % name)
146 exit(1)
147 else:
148 self.results[name] = val
150 # Calls a function on arguments, all is stored in array if
151 # not set previously
152 # (I know this smells like a lisp, but I can't help myself)
154 def check(self):
155 sys.stderr.write("Checking for libraries\n")
156 sys.stderr.write("----------------------\n")
157 for i in self.libraries:
158 if i[0] not in self.results:
159 self.results[i[0]] = i[2][0](self.cfg, *i[2][1:])
160 sys.stderr.write("\n")
162 # Writes '#define HAVE_XXX_H' into passed file
164 def write_config_h(self, f):
165 for i in self.libraries:
166 f.write("/*\n * %s\n */\n" % i[1])
167 if self.results[i[0]]:
168 f.write("#define HAVE_%s\n" % i[0].upper())
169 else:
170 f.write("//#define HAVE_%s\n" % i[0].upper())
171 f.write("\n")
174 # Writes LDLIBS and CFLAGS into passed file
176 def write_config_mk(self, f):
177 for i in self.libraries:
178 f.write("# %s - %s\n" % (i[0], i[1]))
179 if self.results[i[0]]:
180 f.write("HAVE_%s=yes\n" % i[0].upper())
181 # f.write("CFLAGS+=%s\nLDLIBS+=%s\n" % (i[3], i[4]))
182 else:
183 f.write("HAVE_%s=no\n" % i[0].upper())
185 # Write all libraries the library should link with
186 for module in self.get_modules():
187 f.write("# %s linker flags\n" % (module))
188 f.write("LDLIBS_%s=" % (module))
189 f.write("%s\n" % self.get_linker_flags(module))
191 # Return list of linker flags needed to build particular module
192 # (module may be core, loaders, backends, etc...
194 def get_linker_flags(self, module):
195 res = ''
196 for i in self.libraries:
197 if module in i[5] and self.results[i[0]]:
198 if i[4] == '':
199 continue;
200 if res != '':
201 res += ' '
202 res += i[4]
203 return res
205 # Returns list of cflags needed to build module
207 def get_cflags(self, module):
208 res = ''
209 for i in self.libraries:
210 if module in i[5] and self.results[i[0]]:
211 res += ' ' + i[3]
212 return res
215 # Builds a list of GFXprim libraries that may need to be linked against
216 # third party libs
218 def get_modules(self):
219 modules = {}
220 for i in self.libraries:
221 for module in i[5]:
222 modules[module] = True
223 return modules.keys()
225 def die_screaming(msg):
226 sys.stderr.write("\n************************************\n")
227 sys.stderr.write("ERROR: ")
228 sys.stderr.write(msg)
229 sys.stderr.write("\n************************************\n")
230 exit(1)
233 # Check for basic compiling tools
235 def basic_checks(cfg):
236 sys.stderr.write("Basic checks\n")
237 sys.stderr.write("------------\n")
239 if not c_compiler_exists(cfg):
240 die_screaming("No C compiler found")
242 check_for_swig(cfg)
243 check_for_python_config(cfg)
245 if define_fortify_source(cfg):
246 cfg['CFLAGS'][0] = cfg['CFLAGS'][0] + " -D_FORTIFY_SOURCE=2"
248 cfg['PYTHON_VER'][0] = python_version(cfg)
250 if cfg['libdir'][0] == '':
251 sys.stderr.write("Checking for lib directory ... ")
253 if os.path.isdir('/usr/lib64'):
254 cfg['libdir'][0] = 'lib64'
255 else:
256 cfg['libdir'][0] = 'lib'
258 sys.stderr.write(cfg['libdir'][0] + '\n');
260 sys.stderr.write('\n')
263 # Write configuration files
265 def write_config_h(cfg, libs):
266 f = open("config.h", "w")
267 f.write("/*\n * This file is genereated by configure script\n */\n");
268 f.write("#ifndef CONFIG_H\n#define CONFIG_H\n\n")
269 libs.write_config_h(f);
270 f.write("#endif /* CONFIG_H */\n");
271 sys.stderr.write("Config 'config.h' written\n")
272 f.close()
274 def write_config_mk(cfg, libs):
275 f = open('config.gen.mk', 'w')
277 for i in cfg:
278 f.write("# %s\n%s=%s\n" % (cfg[i][1], i, cfg_get_value(i)))
280 libs.write_config_mk(f);
281 f.close()
282 sys.stderr.write("Config 'config.gen.mk' written\n")
285 # Generate app compilation helper
287 def write_gfxprim_config(cfg, libs):
288 modules = libs.get_modules()
289 f = open('gfxprim-config', 'w')
290 f.write('#!/bin/sh\n'
291 '#\n# Generated by configure, do not edit directly\n#\n\n'
292 'USAGE="Usage: $0 --list-modules --cflags --libs --libs-module_foo"\n'
293 '\nif test $# -eq 0; then\n'
294 '\techo "$USAGE"\n'
295 '\texit 1\n'
296 'fi\n\n'
297 'while test -n "$1"; do\n'
298 '\tcase "$1" in\n')
300 # General switches cflags and ldflags
301 f.write('\t--help) echo "$USAGE"; exit 0;;\n')
302 f.write('\t--list-modules) echo "%s"; exit 0;;\n' % ' '.join(modules))
303 f.write('\t--cflags) echo -n "-I/usr/include/gfxprim/%s";;\n' %
304 libs.get_cflags('core'))
305 f.write('\t--libs) echo -n "-lgfxprim -lrt -lm %s ";;\n' % libs.get_linker_flags('core'))
307 # ldflags for specific modules
308 for i in modules:
309 ldflags = ''
310 if i == 'backends':
311 ldflags += '-lgfxprim-backends '
312 if i == 'grabbers':
313 ldflags += '-lgfxprim-grabbers '
314 if i == 'loaders':
315 ldflags += '-lgfxprim-loaders '
316 ldflags += libs.get_linker_flags(i)
317 f.write('\t--libs-%s) echo -n "%s ";;\n' % (i, ldflags))
319 f.write('\t*) echo "Invalid option \'$1\'"; echo $USAGE; exit 1;;\n')
321 f.write('\tesac\n\tshift\ndone\necho\n')
322 f.close()
323 os.system('chmod +x gfxprim-config')
325 def cfg_parse_args(cfg, args):
326 for i in args:
327 par = i.split('=');
328 if (len(par) != 2):
329 die_screaming('Invalid argument %s' % i)
331 if (par[0] not in cfg):
332 die_screaming('Invalid config key %s' % i)
334 cfg[par[0]][0] = par[1]
336 if __name__ == '__main__':
338 # Dictionary for default configuration parameters
340 cfg = {'CC' : ['gcc', 'Path/name of the C compiler'],
341 'CFLAGS' : ['-W -Wall -Wextra -O2 -ggdb', 'C compiler flags'],
342 'PYTHON_BIN' : ['python', 'Path/name of python interpreter'],
343 'SWIG' : ['swig', 'Simplified Wrapper and Interface Generator'],
344 'PYTHON_CONFIG' : ['python-config', 'Python config helper'],
345 'PYTHON_VER' : ['', 'Python version (derived from python config)'],
346 'include_path' : ['/usr/include', 'Path to the system headers'],
347 'prefix' : ['/usr/local/', 'Installation prefix'],
348 'bindir' : ['bin', 'Where to install binaries'],
349 'libdir' : ['', 'Where to install libraries'],
350 'includedir' : ['include', 'Where to install headers'],
351 'mandir' : ['share/man', 'Where to install man pages'],
352 'docdir' : ['share/doc/', 'Where to install documentation'],
353 # Here comes autoconf compatibility cruft, not used for anything yet
354 'infodir' : ['share/info', 'Where to install info pages'],
355 'datadir' : ['share', 'Where to place readonly arch independend datafiles'],
356 'sysconfdir' : ['etc', 'Where to place configuration'],
357 'localstatedir' : ['local/var/', 'Where to place runtime modified datafiles'],
358 'build' : ['', 'WARNING not used'],
359 'host' : ['', 'WARNING not used'],
363 # Library detection/enable disable
365 # name, description, [detection], cflags, ldflags, list of modules library is needed for
367 l = libraries([["libpng",
368 "Portable Network Graphics Library",
369 [header_exists, "png.h"], "", "-lpng", ["loaders"]],
370 ["libsdl",
371 "Simple Direct Media Layer",
372 [header_exists, "SDL/SDL.h"], "", "`sdl-config --libs`", ["backends"]],
373 ["jpeg",
374 "Library to load, handle and manipulate images in the JPEG format",
375 [header_exists, "jpeglib.h"], "", "-ljpeg", ["loaders"]],
376 ["openjpeg",
377 "An open-source JPEG 2000 library",
378 [header_exists, "openjpeg-2.0/openjpeg.h"], "", "-lopenjp2", ["loaders"]],
379 ["giflib",
380 "Library to handle, display and manipulate GIF images",
381 [header_exists, "gif_lib.h"], "", "-lgif", ["loaders"]],
382 ["tiff",
383 "Tag Image File Format (TIFF) library",
384 [header_exists, "tiffio.h"], "", "-ltiff", ["loaders"]],
385 ["zlib",
386 "Standard (de)compression library",
387 [header_exists, "zlib.h"], "", "-lz", ["loaders"]],
388 ["libX11",
389 "X11 library",
390 [header_exists, "X11/Xlib.h"], "", "-lX11", ["backends"]],
391 ["X_SHM",
392 "MIT-SHM X Extension",
393 [header_exists, "X11/extensions/XShm.h"], "", "-lXext", ["backends"]],
394 ["aalib",
395 "Portable ascii art GFX library",
396 [header_exists, "aalib.h"], "", "-laa", ["backends"]],
397 ["freetype",
398 "A high-quality and portable font engine",
399 [header_exists, "ft2build.h", "freetype2/ft2build.h"],
400 "", "`freetype-config --libs`", ["core"]],
401 ["dl",
402 "Dynamic linker",
403 [header_exists, "dlfcn.h"], "", "-ldl", ["core"]],
404 ["V4L2",
405 "Video for linux 2",
406 [header_exists, "linux/videodev2.h"], "", "", ["grabbers"]],
407 ["libvterm",
408 "Implementation of a VT220/xterm/ECMA-48 terminal emulator",
409 [header_exists, "vterm.h"], "", "", [""]],
410 ["pthread",
411 "Posix Threads",
412 [header_exists, "pthread.h"], "-pthread", "-pthread", ["core"]],
413 ["backtrace",
414 "C stack trace writeout",
415 [c_try_compile, "#include <execinfo.h>\nint main(void) { backtrace(0, 0); }",
416 "Checking for backtrace() ... "], "", "", ["core"]]], cfg)
418 parser = OptionParser();
420 # Get configuration parameters from environment variables
421 for i in cfg:
422 if i in os.environ:
423 cfg[i][0] = os.environ[i]
425 # Enable disable libraries for linking
426 parser.add_option("-e", "--enable", dest="enable", action="append",
427 help="force enable library linking", metavar="libfoo")
428 parser.add_option("-d", "--disable", dest="disable", action="append",
429 help="disable library linking", metavar="libfoo")
431 # Add cfg config options
432 for i in cfg:
433 parser.add_option("", "--"+i, dest=i, metavar=cfg[i][0], help=cfg[i][1])
435 (options, args) = parser.parse_args();
438 # Enable/Disable libraries as user requested
439 # These are not checked later
441 if options.enable:
442 for i in options.enable:
443 l.set(i, True);
444 if options.disable:
445 for i in options.disable:
446 l.set(i, False);
448 for i in cfg:
449 if getattr(options, i) is not None:
450 cfg[i][0] = getattr(options, i)
453 # Handle args such as CC=gcc passed after options
455 cfg_parse_args(cfg, args)
457 basic_checks(cfg);
459 l.check()
460 l.print_summary()
462 write_config_h(cfg, l)
463 write_config_mk(cfg, l)
464 write_gfxprim_config(cfg, l)