Merge branch 'master' of ctdb into 'master' of samba
[samba.git] / buildtools / wafadmin / Tools / config_c.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy, 2005-2008 (ita)
4
5 """
6 c/c++ configuration routines
7 """
8
9 import os, imp, sys, shlex, shutil
10 from Utils import md5
11 import Build, Utils, Configure, Task, Options, Logs, TaskGen
12 from Constants import *
13 from Configure import conf, conftest
14
15 cfg_ver = {
16         'atleast-version': '>=',
17         'exact-version': '==',
18         'max-version': '<=',
19 }
20
21 SNIP1 = '''
22         int main() {
23         void *p;
24         p=(void*)(%s);
25         return 0;
26 }
27 '''
28
29 SNIP2 = '''
30 int main() {
31         if ((%(type_name)s *) 0) return 0;
32         if (sizeof (%(type_name)s)) return 0;
33 }
34 '''
35
36 SNIP3 = '''
37 int main() {
38         return 0;
39 }
40 '''
41
42 def parse_flags(line, uselib, env):
43         """pkg-config still has bugs on some platforms, and there are many -config programs, parsing flags is necessary :-/"""
44
45         lst = shlex.split(line)
46         while lst:
47                 x = lst.pop(0)
48                 st = x[:2]
49                 ot = x[2:]
50                 app = env.append_value
51                 if st == '-I' or st == '/I':
52                         if not ot: ot = lst.pop(0)
53                         app('CPPPATH_' + uselib, ot)
54                 elif st == '-D':
55                         if not ot: ot = lst.pop(0)
56                         app('CXXDEFINES_' + uselib, ot)
57                         app('CCDEFINES_' + uselib, ot)
58                 elif st == '-l':
59                         if not ot: ot = lst.pop(0)
60                         app('LIB_' + uselib, ot)
61                 elif st == '-L':
62                         if not ot: ot = lst.pop(0)
63                         app('LIBPATH_' + uselib, ot)
64                 elif x == '-pthread' or x.startswith('+'):
65                         app('CCFLAGS_' + uselib, x)
66                         app('CXXFLAGS_' + uselib, x)
67                         app('LINKFLAGS_' + uselib, x)
68                 elif x == '-framework':
69                         app('FRAMEWORK_' + uselib, lst.pop(0))
70                 elif x.startswith('-F'):
71                         app('FRAMEWORKPATH_' + uselib, x[2:])
72                 elif x.startswith('-std'):
73                         app('CCFLAGS_' + uselib, x)
74                         app('CXXFLAGS_' + uselib, x)
75                         app('LINKFLAGS_' + uselib, x)
76                 #
77                 # NOTE on special treatment of -Wl,-R and -Wl,-rpath:
78                 #
79                 # It is important to not put a library provided RPATH
80                 # into the LINKFLAGS but in the RPATH instead, since
81                 # the provided LINKFLAGS get prepended to our own internal
82                 # RPATH later, and hence can potentially lead to linking
83                 # in too old versions of our internal libs.
84                 #
85                 elif x.startswith('-Wl,-R'):
86                         app('RPATH_' + uselib, x[6:])
87                 elif x.startswith('-Wl,-rpath,'):
88                         app('RPATH_' + uselib, x[11:])
89                 elif x.startswith('-Wl'):
90                         app('LINKFLAGS_' + uselib, x)
91                 elif x.startswith('-m') or x.startswith('-f'):
92                         app('CCFLAGS_' + uselib, x)
93                         app('CXXFLAGS_' + uselib, x)
94
95 @conf
96 def ret_msg(self, f, kw):
97         """execute a function, when provided"""
98         if isinstance(f, str):
99                 return f
100         return f(kw)
101
102 @conf
103 def validate_cfg(self, kw):
104         if not 'path' in kw:
105                 kw['path'] = 'pkg-config --errors-to-stdout --print-errors'
106
107         # pkg-config version
108         if 'atleast_pkgconfig_version' in kw:
109                 if not 'msg' in kw:
110                         kw['msg'] = 'Checking for pkg-config version >= %s' % kw['atleast_pkgconfig_version']
111                 return
112
113         # pkg-config --modversion
114         if 'modversion' in kw:
115                 return
116
117         if 'variables' in kw:
118                 if not 'msg' in kw:
119                         kw['msg'] = 'Checking for %s variables' % kw['package']
120                 return
121
122         # checking for the version of a module, for the moment, one thing at a time
123         for x in cfg_ver.keys():
124                 y = x.replace('-', '_')
125                 if y in kw:
126                         if not 'package' in kw:
127                                 raise ValueError('%s requires a package' % x)
128
129                         if not 'msg' in kw:
130                                 kw['msg'] = 'Checking for %s %s %s' % (kw['package'], cfg_ver[x], kw[y])
131                         return
132
133         if not 'msg' in kw:
134                 kw['msg'] = 'Checking for %s' % (kw['package'] or kw['path'])
135         if not 'okmsg' in kw:
136                 kw['okmsg'] = 'yes'
137         if not 'errmsg' in kw:
138                 kw['errmsg'] = 'not found'
139
140 @conf
141 def cmd_and_log(self, cmd, kw):
142         Logs.debug('runner: %s\n' % cmd)
143         if self.log:
144                 self.log.write('%s\n' % cmd)
145
146         try:
147                 p = Utils.pproc.Popen(cmd, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE, shell=True)
148                 (out, err) = p.communicate()
149         except OSError, e:
150                 self.log.write('error %r' % e)
151                 self.fatal(str(e))
152
153         # placeholder, don't touch
154         out = str(out)
155         err = str(err)
156
157         if self.log:
158                 self.log.write(out)
159                 self.log.write(err)
160
161         if p.returncode:
162                 if not kw.get('errmsg', ''):
163                         if kw.get('mandatory', False):
164                                 kw['errmsg'] = out.strip()
165                         else:
166                                 kw['errmsg'] = 'no'
167                 self.fatal('fail')
168         return out
169
170 @conf
171 def exec_cfg(self, kw):
172
173         # pkg-config version
174         if 'atleast_pkgconfig_version' in kw:
175                 cmd = '%s --atleast-pkgconfig-version=%s' % (kw['path'], kw['atleast_pkgconfig_version'])
176                 self.cmd_and_log(cmd, kw)
177                 if not 'okmsg' in kw:
178                         kw['okmsg'] = 'yes'
179                 return
180
181         # checking for the version of a module
182         for x in cfg_ver:
183                 y = x.replace('-', '_')
184                 if y in kw:
185                         self.cmd_and_log('%s --%s=%s %s' % (kw['path'], x, kw[y], kw['package']), kw)
186                         if not 'okmsg' in kw:
187                                 kw['okmsg'] = 'yes'
188                         self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0)
189                         break
190
191         # retrieving the version of a module
192         if 'modversion' in kw:
193                 version = self.cmd_and_log('%s --modversion %s' % (kw['path'], kw['modversion']), kw).strip()
194                 self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version)
195                 return version
196
197         # retrieving variables of a module
198         if 'variables' in kw:
199                 env = kw.get('env', self.env)
200                 uselib = kw.get('uselib_store', kw['package'].upper())
201                 vars = Utils.to_list(kw['variables'])
202                 for v in vars:
203                         val = self.cmd_and_log('%s --variable=%s %s' % (kw['path'], v, kw['package']), kw).strip()
204                         var = '%s_%s' % (uselib, v)
205                         env[var] = val
206                 if not 'okmsg' in kw:
207                         kw['okmsg'] = 'yes'
208                 return
209
210         lst = [kw['path']]
211
212
213         defi = kw.get('define_variable', None)
214         if not defi:
215                 defi = self.env.PKG_CONFIG_DEFINES or {}
216         for key, val in defi.iteritems():
217                 lst.append('--define-variable=%s=%s' % (key, val))
218
219         lst.append(kw.get('args', ''))
220         lst.append(kw['package'])
221
222         # so we assume the command-line will output flags to be parsed afterwards
223         cmd = ' '.join(lst)
224         ret = self.cmd_and_log(cmd, kw)
225         if not 'okmsg' in kw:
226                 kw['okmsg'] = 'yes'
227
228         self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0)
229         parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env))
230         return ret
231
232 @conf
233 def check_cfg(self, *k, **kw):
234         """
235         for pkg-config mostly, but also all the -config tools
236         conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI')
237         conf.check_cfg(package='dbus-1', variables='system_bus_default_address session_bus_services_dir')
238         """
239
240         self.validate_cfg(kw)
241         if 'msg' in kw:
242                 self.check_message_1(kw['msg'])
243         ret = None
244         try:
245                 ret = self.exec_cfg(kw)
246         except Configure.ConfigurationError, e:
247                 if 'errmsg' in kw:
248                         self.check_message_2(kw['errmsg'], 'YELLOW')
249                 if 'mandatory' in kw and kw['mandatory']:
250                         if Logs.verbose > 1:
251                                 raise
252                         else:
253                                 self.fatal('the configuration failed (see %r)' % self.log.name)
254         else:
255                 kw['success'] = ret
256                 if 'okmsg' in kw:
257                         self.check_message_2(self.ret_msg(kw['okmsg'], kw))
258
259         return ret
260
261 # the idea is the following: now that we are certain
262 # that all the code here is only for c or c++, it is
263 # easy to put all the logic in one function
264 #
265 # this should prevent code duplication (ita)
266
267 # env: an optional environment (modified -> provide a copy)
268 # compiler: cc or cxx - it tries to guess what is best
269 # type: cprogram, cshlib, cstaticlib
270 # code: a c code to execute
271 # uselib_store: where to add the variables
272 # uselib: parameters to use for building
273 # define: define to set, like FOO in #define FOO, if not set, add /* #undef FOO */
274 # execute: True or False - will return the result of the execution
275
276 @conf
277 def validate_c(self, kw):
278         """validate the parameters for the test method"""
279
280         if not 'env' in kw:
281                 kw['env'] = self.env.copy()
282
283         env = kw['env']
284         if not 'compiler' in kw:
285                 kw['compiler'] = 'cc'
286                 if env['CXX_NAME'] and Task.TaskBase.classes.get('cxx', None):
287                         kw['compiler'] = 'cxx'
288                         if not self.env['CXX']:
289                                 self.fatal('a c++ compiler is required')
290                 else:
291                         if not self.env['CC']:
292                                 self.fatal('a c compiler is required')
293
294         if not 'type' in kw:
295                 kw['type'] = 'cprogram'
296
297         assert not(kw['type'] != 'cprogram' and kw.get('execute', 0)), 'can only execute programs'
298
299
300         #if kw['type'] != 'program' and kw.get('execute', 0):
301         #       raise ValueError, 'can only execute programs'
302
303         def to_header(dct):
304                 if 'header_name' in dct:
305                         dct = Utils.to_list(dct['header_name'])
306                         return ''.join(['#include <%s>\n' % x for x in dct])
307                 return ''
308
309         # set the file name
310         if not 'compile_mode' in kw:
311                 kw['compile_mode'] = (kw['compiler'] == 'cxx') and 'cxx' or 'cc'
312
313         if not 'compile_filename' in kw:
314                 kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '')
315
316         #OSX
317         if 'framework_name' in kw:
318                 try: TaskGen.task_gen.create_task_macapp
319                 except AttributeError: self.fatal('frameworks require the osx tool')
320
321                 fwkname = kw['framework_name']
322                 if not 'uselib_store' in kw:
323                         kw['uselib_store'] = fwkname.upper()
324
325                 if not kw.get('no_header', False):
326                         if not 'header_name' in kw:
327                                 kw['header_name'] = []
328                         fwk = '%s/%s.h' % (fwkname, fwkname)
329                         if kw.get('remove_dot_h', None):
330                                 fwk = fwk[:-2]
331                         kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk]
332
333                 kw['msg'] = 'Checking for framework %s' % fwkname
334                 kw['framework'] = fwkname
335                 #kw['frameworkpath'] = set it yourself
336
337         if 'function_name' in kw:
338                 fu = kw['function_name']
339                 if not 'msg' in kw:
340                         kw['msg'] = 'Checking for function %s' % fu
341                 kw['code'] = to_header(kw) + SNIP1 % fu
342                 if not 'uselib_store' in kw:
343                         kw['uselib_store'] = fu.upper()
344                 if not 'define_name' in kw:
345                         kw['define_name'] = self.have_define(fu)
346
347         elif 'type_name' in kw:
348                 tu = kw['type_name']
349                 if not 'msg' in kw:
350                         kw['msg'] = 'Checking for type %s' % tu
351                 if not 'header_name' in kw:
352                         kw['header_name'] = 'stdint.h'
353                 kw['code'] = to_header(kw) + SNIP2 % {'type_name' : tu}
354                 if not 'define_name' in kw:
355                         kw['define_name'] = self.have_define(tu.upper())
356
357         elif 'header_name' in kw:
358                 if not 'msg' in kw:
359                         kw['msg'] = 'Checking for header %s' % kw['header_name']
360
361                 l = Utils.to_list(kw['header_name'])
362                 assert len(l)>0, 'list of headers in header_name is empty'
363
364                 kw['code'] = to_header(kw) + SNIP3
365
366                 if not 'uselib_store' in kw:
367                         kw['uselib_store'] = l[0].upper()
368
369                 if not 'define_name' in kw:
370                         kw['define_name'] = self.have_define(l[0])
371
372         if 'lib' in kw:
373                 if not 'msg' in kw:
374                         kw['msg'] = 'Checking for library %s' % kw['lib']
375                 if not 'uselib_store' in kw:
376                         kw['uselib_store'] = kw['lib'].upper()
377
378         if 'staticlib' in kw:
379                 if not 'msg' in kw:
380                         kw['msg'] = 'Checking for static library %s' % kw['staticlib']
381                 if not 'uselib_store' in kw:
382                         kw['uselib_store'] = kw['staticlib'].upper()
383
384         if 'fragment' in kw:
385                 # an additional code fragment may be provided to replace the predefined code
386                 # in custom headers
387                 kw['code'] = kw['fragment']
388                 if not 'msg' in kw:
389                         kw['msg'] = 'Checking for custom code'
390                 if not 'errmsg' in kw:
391                         kw['errmsg'] = 'no'
392
393         for (flagsname,flagstype) in [('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')]:
394                 if flagsname in kw:
395                         if not 'msg' in kw:
396                                 kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname])
397                         if not 'errmsg' in kw:
398                                 kw['errmsg'] = 'no'
399
400         if not 'execute' in kw:
401                 kw['execute'] = False
402
403         if not 'errmsg' in kw:
404                 kw['errmsg'] = 'not found'
405
406         if not 'okmsg' in kw:
407                 kw['okmsg'] = 'yes'
408
409         if not 'code' in kw:
410                 kw['code'] = SNIP3
411
412         if not kw.get('success'): kw['success'] = None
413
414         assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c'
415
416 @conf
417 def post_check(self, *k, **kw):
418         "set the variables after a test was run successfully"
419
420         is_success = False
421         if kw['execute']:
422                 if kw['success'] is not None:
423                         is_success = True
424         else:
425                 is_success = (kw['success'] == 0)
426
427         if 'define_name' in kw:
428                 if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw:
429                         if kw['execute']:
430                                 key = kw['success']
431                                 if isinstance(key, str):
432                                         if key:
433                                                 self.define(kw['define_name'], key, quote=kw.get('quote', 1))
434                                         else:
435                                                 self.define_cond(kw['define_name'], True)
436                                 else:
437                                         self.define_cond(kw['define_name'], False)
438                         else:
439                                 self.define_cond(kw['define_name'], is_success)
440
441         if is_success and 'uselib_store' in kw:
442                 import cc, cxx
443                 for k in set(cc.g_cc_flag_vars).union(cxx.g_cxx_flag_vars):
444                         lk = k.lower()
445                         # inconsistency: includes -> CPPPATH
446                         if k == 'CPPPATH': lk = 'includes'
447                         if k == 'CXXDEFINES': lk = 'defines'
448                         if k == 'CCDEFINES': lk = 'defines'
449                         if lk in kw:
450                                 val = kw[lk]
451                                 # remove trailing slash
452                                 if isinstance(val, str):
453                                         val = val.rstrip(os.path.sep)
454                                 self.env.append_unique(k + '_' + kw['uselib_store'], val)
455
456 @conf
457 def check(self, *k, **kw):
458         # so this will be the generic function
459         # it will be safer to use check_cxx or check_cc
460         self.validate_c(kw)
461         self.check_message_1(kw['msg'])
462         ret = None
463         try:
464                 ret = self.run_c_code(*k, **kw)
465         except Configure.ConfigurationError, e:
466                 self.check_message_2(kw['errmsg'], 'YELLOW')
467                 if 'mandatory' in kw and kw['mandatory']:
468                         if Logs.verbose > 1:
469                                 raise
470                         else:
471                                 self.fatal('the configuration failed (see %r)' % self.log.name)
472         else:
473                 kw['success'] = ret
474                 self.check_message_2(self.ret_msg(kw['okmsg'], kw))
475
476         self.post_check(*k, **kw)
477         if not kw.get('execute', False):
478                 return ret == 0
479         return ret
480
481 @conf
482 def run_c_code(self, *k, **kw):
483         test_f_name = kw['compile_filename']
484
485         k = 0
486         while k < 10000:
487                 # make certain to use a fresh folder - necessary for win32
488                 dir = os.path.join(self.blddir, '.conf_check_%d' % k)
489
490                 # if the folder already exists, remove it
491                 try:
492                         shutil.rmtree(dir)
493                 except OSError:
494                         pass
495
496                 try:
497                         os.stat(dir)
498                 except OSError:
499                         break
500
501                 k += 1
502
503         try:
504                 os.makedirs(dir)
505         except:
506                 self.fatal('cannot create a configuration test folder %r' % dir)
507
508         try:
509                 os.stat(dir)
510         except:
511                 self.fatal('cannot use the configuration test folder %r' % dir)
512
513         bdir = os.path.join(dir, 'testbuild')
514
515         if not os.path.exists(bdir):
516                 os.makedirs(bdir)
517
518         env = kw['env']
519
520         dest = open(os.path.join(dir, test_f_name), 'w')
521         dest.write(kw['code'])
522         dest.close()
523
524         back = os.path.abspath('.')
525
526         bld = Build.BuildContext()
527         bld.log = self.log
528         bld.all_envs.update(self.all_envs)
529         bld.all_envs['default'] = env
530         bld.lst_variants = bld.all_envs.keys()
531         bld.load_dirs(dir, bdir)
532
533         os.chdir(dir)
534
535         bld.rescan(bld.srcnode)
536
537         if not 'features' in kw:
538                 # conf.check(features='cc cprogram pyext', ...)
539                 kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram cc"
540
541         o = bld(features=kw['features'], source=test_f_name, target='testprog')
542
543         for k, v in kw.iteritems():
544                 setattr(o, k, v)
545
546         self.log.write("==>\n%s\n<==\n" % kw['code'])
547
548         # compile the program
549         try:
550                 bld.compile()
551         except Utils.WafError:
552                 ret = Utils.ex_stack()
553         else:
554                 ret = 0
555
556         # chdir before returning
557         os.chdir(back)
558
559         if ret:
560                 self.log.write('command returned %r' % ret)
561                 self.fatal(str(ret))
562
563         # if we need to run the program, try to get its result
564         # keep the name of the program to execute
565         if kw['execute']:
566                 lastprog = o.link_task.outputs[0].abspath(env)
567
568                 args = Utils.to_list(kw.get('exec_args', []))
569                 proc = Utils.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE)
570                 (out, err) = proc.communicate()
571                 w = self.log.write
572                 w(str(out))
573                 w('\n')
574                 w(str(err))
575                 w('\n')
576                 w('returncode %r' % proc.returncode)
577                 w('\n')
578                 if proc.returncode:
579                         self.fatal(Utils.ex_stack())
580                 ret = out
581
582         return ret
583
584 @conf
585 def check_cxx(self, *k, **kw):
586         kw['compiler'] = 'cxx'
587         return self.check(*k, **kw)
588
589 @conf
590 def check_cc(self, *k, **kw):
591         kw['compiler'] = 'cc'
592         return self.check(*k, **kw)
593
594 @conf
595 def define(self, define, value, quote=1):
596         """store a single define and its state into an internal list for later
597            writing to a config header file.  Value can only be
598            a string or int; other types not supported.  String
599            values will appear properly quoted in the generated
600            header file."""
601         assert define and isinstance(define, str)
602
603         # ordered_dict is for writing the configuration header in order
604         tbl = self.env[DEFINES] or Utils.ordered_dict()
605
606         # the user forgot to tell if the value is quoted or not
607         if isinstance(value, str):
608                 if quote:
609                         tbl[define] = '"%s"' % repr('"'+value)[2:-1].replace('"', '\\"')
610                 else:
611                         tbl[define] = value
612         elif isinstance(value, int):
613                 tbl[define] = value
614         else:
615                 raise TypeError('define %r -> %r must be a string or an int' % (define, value))
616
617         # add later to make reconfiguring faster
618         self.env[DEFINES] = tbl
619         self.env[define] = value # <- not certain this is necessary
620
621 @conf
622 def undefine(self, define):
623         """store a single define and its state into an internal list
624            for later writing to a config header file"""
625         assert define and isinstance(define, str)
626
627         tbl = self.env[DEFINES] or Utils.ordered_dict()
628
629         value = UNDEFINED
630         tbl[define] = value
631
632         # add later to make reconfiguring faster
633         self.env[DEFINES] = tbl
634         self.env[define] = value
635
636 @conf
637 def define_cond(self, name, value):
638         """Conditionally define a name.
639         Formally equivalent to: if value: define(name, 1) else: undefine(name)"""
640         if value:
641                 self.define(name, 1)
642         else:
643                 self.undefine(name)
644
645 @conf
646 def is_defined(self, key):
647         defines = self.env[DEFINES]
648         if not defines:
649                 return False
650         try:
651                 value = defines[key]
652         except KeyError:
653                 return False
654         else:
655                 return value != UNDEFINED
656
657 @conf
658 def get_define(self, define):
659         "get the value of a previously stored define"
660         try: return self.env[DEFINES][define]
661         except KeyError: return None
662
663 @conf
664 def have_define(self, name):
665         "prefix the define with 'HAVE_' and make sure it has valid characters."
666         return self.__dict__.get('HAVE_PAT', 'HAVE_%s') % Utils.quote_define_name(name)
667
668 @conf
669 def write_config_header(self, configfile='', env='', guard='', top=False):
670         "save the defines into a file"
671         if not configfile: configfile = WAF_CONFIG_H
672         waf_guard = guard or '_%s_WAF' % Utils.quote_define_name(configfile)
673
674         # configfile -> absolute path
675         # there is a good reason to concatenate first and to split afterwards
676         if not env: env = self.env
677         if top:
678                 diff = ''
679         else:
680                 diff = Utils.diff_path(self.srcdir, self.curdir)
681         full = os.sep.join([self.blddir, env.variant(), diff, configfile])
682         full = os.path.normpath(full)
683         (dir, base) = os.path.split(full)
684
685         try: os.makedirs(dir)
686         except: pass
687
688         dest = open(full, 'w')
689         dest.write('/* Configuration header created by Waf - do not edit */\n')
690         dest.write('#ifndef %s\n#define %s\n\n' % (waf_guard, waf_guard))
691
692         dest.write(self.get_config_header())
693
694         # config files are not removed on "waf clean"
695         env.append_unique(CFG_FILES, os.path.join(diff, configfile))
696
697         dest.write('\n#endif /* %s */\n' % waf_guard)
698         dest.close()
699
700 @conf
701 def get_config_header(self):
702         """Fill-in the contents of the config header. Override when you need to write your own config header."""
703         config_header = []
704
705         tbl = self.env[DEFINES] or Utils.ordered_dict()
706         for key in tbl.allkeys:
707                 value = tbl[key]
708                 if value is None:
709                         config_header.append('#define %s' % key)
710                 elif value is UNDEFINED:
711                         config_header.append('/* #undef %s */' % key)
712                 else:
713                         config_header.append('#define %s %s' % (key, value))
714         return "\n".join(config_header)
715
716 @conftest
717 def find_cpp(conf):
718         v = conf.env
719         cpp = []
720         if v['CPP']: cpp = v['CPP']
721         elif 'CPP' in conf.environ: cpp = conf.environ['CPP']
722         if not cpp: cpp = conf.find_program('cpp', var='CPP')
723         #if not cpp: cpp = v['CC']
724         #if not cpp: cpp = v['CXX']
725         v['CPP'] = cpp
726
727 @conftest
728 def cc_add_flags(conf):
729         conf.add_os_flags('CFLAGS', 'CCFLAGS')
730         conf.add_os_flags('CPPFLAGS')
731
732 @conftest
733 def cxx_add_flags(conf):
734         conf.add_os_flags('CXXFLAGS')
735         conf.add_os_flags('CPPFLAGS')
736
737 @conftest
738 def link_add_flags(conf):
739         conf.add_os_flags('LINKFLAGS')
740         conf.add_os_flags('LDFLAGS', 'LINKFLAGS')
741
742 @conftest
743 def cc_load_tools(conf):
744         conf.check_tool('cc')
745
746 @conftest
747 def cxx_load_tools(conf):
748         conf.check_tool('cxx')
749