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