third_party:waf: update to upstream 2.0.4 release
[samba.git] / buildtools / wafsamba / samba_autoconf.py
1 # a waf tool to add autoconf-like macros to the configure section
2
3 import os, sys
4 from waflib import Build, Options, Logs, Context
5 from waflib.Configure import conf
6 from waflib.TaskGen import feature
7 from waflib.Tools import c_preproc as preproc
8 from samba_utils import TO_LIST, GET_TARGET_TYPE, SET_TARGET_TYPE, unique_list, mkdir_p
9
10 missing_headers = set()
11
12 ####################################################
13 # some autoconf like helpers, to make the transition
14 # to waf a bit easier for those used to autoconf
15 # m4 files
16
17 @conf
18 def DEFINE(conf, d, v, add_to_cflags=False, quote=False):
19     '''define a config option'''
20     conf.define(d, v, quote=quote)
21     if add_to_cflags:
22         conf.env.append_value('CFLAGS', '-D%s=%s' % (d, str(v)))
23
24 def hlist_to_string(conf, headers=None):
25     '''convert a headers list to a set of #include lines'''
26     hdrs=''
27     hlist = conf.env.hlist
28     if headers:
29         hlist = hlist[:]
30         hlist.extend(TO_LIST(headers))
31     for h in hlist:
32         hdrs += '#include <%s>\n' % h
33     return hdrs
34
35
36 @conf
37 def COMPOUND_START(conf, msg):
38     '''start a compound test'''
39     def null_check_message_1(self,*k,**kw):
40         return
41     def null_check_message_2(self,*k,**kw):
42         return
43
44     v = getattr(conf.env, 'in_compound', [])
45     if v != [] and v != 0:
46         conf.env.in_compound = v + 1
47         return
48     conf.start_msg(msg)
49     conf.saved_check_message_1 = conf.start_msg
50     conf.start_msg = null_check_message_1
51     conf.saved_check_message_2 = conf.end_msg
52     conf.end_msg = null_check_message_2
53     conf.env.in_compound = 1
54
55
56 @conf
57 def COMPOUND_END(conf, result):
58     '''start a compound test'''
59     conf.env.in_compound -= 1
60     if conf.env.in_compound != 0:
61         return
62     conf.start_msg = conf.saved_check_message_1
63     conf.end_msg = conf.saved_check_message_2
64     p = conf.end_msg
65     if result is True:
66         p('ok')
67     elif not result:
68         p('not found', 'YELLOW')
69     else:
70         p(result)
71
72
73 @feature('nolink')
74 def nolink(self):
75     '''using the nolink type in conf.check() allows us to avoid
76        the link stage of a test, thus speeding it up for tests
77        that where linking is not needed'''
78     pass
79
80
81 def CHECK_HEADER(conf, h, add_headers=False, lib=None):
82     '''check for a header'''
83     if h in missing_headers and lib is None:
84         return False
85     d = h.upper().replace('/', '_')
86     d = d.replace('.', '_')
87     d = d.replace('-', '_')
88     d = 'HAVE_%s' % d
89     if CONFIG_SET(conf, d):
90         if add_headers:
91             if not h in conf.env.hlist:
92                 conf.env.hlist.append(h)
93         return True
94
95     (ccflags, ldflags, cpppath) = library_flags(conf, lib)
96
97     hdrs = hlist_to_string(conf, headers=h)
98     if lib is None:
99         lib = ""
100     ret = conf.check(fragment='%s\nint main(void) { return 0; }' % hdrs,
101                      type='nolink',
102                      execute=0,
103                      cflags=ccflags,
104                      mandatory=False,
105                      includes=cpppath,
106                      uselib=lib.upper(),
107                      msg="Checking for header %s" % h)
108     if not ret:
109         missing_headers.add(h)
110         return False
111
112     conf.DEFINE(d, 1)
113     if add_headers and not h in conf.env.hlist:
114         conf.env.hlist.append(h)
115     return ret
116
117
118 @conf
119 def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None):
120     '''check for a list of headers
121
122     when together==True, then the headers accumulate within this test.
123     This is useful for interdependent headers
124     '''
125     ret = True
126     if not add_headers and together:
127         saved_hlist = conf.env.hlist[:]
128         set_add_headers = True
129     else:
130         set_add_headers = add_headers
131     for hdr in TO_LIST(headers):
132         if not CHECK_HEADER(conf, hdr, set_add_headers, lib=lib):
133             ret = False
134     if not add_headers and together:
135         conf.env.hlist = saved_hlist
136     return ret
137
138
139 def header_list(conf, headers=None, lib=None):
140     '''form a list of headers which exist, as a string'''
141     hlist=[]
142     if headers is not None:
143         for h in TO_LIST(headers):
144             if CHECK_HEADER(conf, h, add_headers=False, lib=lib):
145                 hlist.append(h)
146     return hlist_to_string(conf, headers=hlist)
147
148
149 @conf
150 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
151     '''check for a single type'''
152     if define is None:
153         define = 'HAVE_' + t.upper().replace(' ', '_')
154     if msg is None:
155         msg='Checking for %s' % t
156     ret = CHECK_CODE(conf, '%s _x' % t,
157                      define,
158                      execute=False,
159                      headers=headers,
160                      local_include=False,
161                      msg=msg,
162                      lib=lib,
163                      link=False)
164     if not ret and alternate:
165         conf.DEFINE(t, alternate)
166     return ret
167
168
169 @conf
170 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
171     '''check for a list of types'''
172     ret = True
173     for t in TO_LIST(list):
174         if not CHECK_TYPE(conf, t, headers=headers,
175                           define=define, alternate=alternate, lib=lib):
176             ret = False
177     return ret
178
179
180 @conf
181 def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
182     '''check for a single type with a header'''
183     return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
184
185
186 @conf
187 def CHECK_VARIABLE(conf, v, define=None, always=False,
188                    headers=None, msg=None, lib=None):
189     '''check for a variable declaration (or define)'''
190     if define is None:
191         define = 'HAVE_%s' % v.upper()
192
193     if msg is None:
194         msg="Checking for variable %s" % v
195
196     return CHECK_CODE(conf,
197                       # we need to make sure the compiler doesn't
198                       # optimize it out...
199                       '''
200                       #ifndef %s
201                       void *_x; _x=(void *)&%s; return (int)_x;
202                       #endif
203                       return 0
204                       ''' % (v, v),
205                       execute=False,
206                       link=False,
207                       msg=msg,
208                       local_include=False,
209                       lib=lib,
210                       headers=headers,
211                       define=define,
212                       always=always)
213
214
215 @conf
216 def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False):
217     '''check a list of variable declarations, using the HAVE_DECL_xxx form
218        of define
219
220        When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
221        '''
222     ret = True
223     for v in TO_LIST(vars):
224         if not reverse:
225             define='HAVE_DECL_%s' % v.upper()
226         else:
227             define='HAVE_%s_DECL' % v.upper()
228         if not CHECK_VARIABLE(conf, v,
229                               define=define,
230                               headers=headers,
231                               msg='Checking for declaration of %s' % v,
232                               always=always):
233             if not CHECK_CODE(conf,
234                       '''
235                       return (int)%s;
236                       ''' % (v),
237                       execute=False,
238                       link=False,
239                       msg='Checking for declaration of %s (as enum)' % v,
240                       local_include=False,
241                       headers=headers,
242                       define=define,
243                       always=always):
244                 ret = False
245     return ret
246
247
248 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
249     '''check for a function'''
250     define='HAVE_%s' % f.upper()
251
252     ret = False
253
254     conf.COMPOUND_START('Checking for %s' % f)
255
256     if link is None or link:
257         ret = CHECK_CODE(conf,
258                          # this is based on the autoconf strategy
259                          '''
260                          #define %s __fake__%s
261                          #ifdef HAVE_LIMITS_H
262                          # include <limits.h>
263                          #else
264                          # include <assert.h>
265                          #endif
266                          #undef %s
267                          #if defined __stub_%s || defined __stub___%s
268                          #error "bad glibc stub"
269                          #endif
270                          extern char %s();
271                          int main() { return %s(); }
272                          ''' % (f, f, f, f, f, f, f),
273                          execute=False,
274                          link=True,
275                          addmain=False,
276                          add_headers=False,
277                          define=define,
278                          local_include=False,
279                          lib=lib,
280                          headers=headers,
281                          msg='Checking for %s' % f)
282
283         if not ret:
284             ret = CHECK_CODE(conf,
285                              # it might be a macro
286                              # we need to make sure the compiler doesn't
287                              # optimize it out...
288                              'void *__x = (void *)%s; return (int)__x' % f,
289                              execute=False,
290                              link=True,
291                              addmain=True,
292                              add_headers=True,
293                              define=define,
294                              local_include=False,
295                              lib=lib,
296                              headers=headers,
297                              msg='Checking for macro %s' % f)
298
299     if not ret and (link is None or not link):
300         ret = CHECK_VARIABLE(conf, f,
301                              define=define,
302                              headers=headers,
303                              msg='Checking for declaration of %s' % f)
304     conf.COMPOUND_END(ret)
305     return ret
306
307
308 @conf
309 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
310     '''check for a list of functions'''
311     ret = True
312     for f in TO_LIST(list):
313         if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
314             ret = False
315     return ret
316
317
318 @conf
319 def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True):
320     '''check the size of a type'''
321     for v in TO_LIST(vars):
322         v_define = define
323         ret = False
324         if v_define is None:
325             v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
326         for size in list((1, 2, 4, 8, 16, 32)):
327             if CHECK_CODE(conf,
328                       'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size),
329                       define=v_define,
330                       quote=False,
331                       headers=headers,
332                       local_include=False,
333                       msg="Checking if size of %s == %d" % (v, size)):
334                 conf.DEFINE(v_define, size)
335                 ret = True
336                 break
337         if not ret and critical:
338             Logs.error("Couldn't determine size of '%s'" % v)
339             sys.exit(1)
340     return ret
341
342 @conf
343 def CHECK_VALUEOF(conf, v, headers=None, define=None):
344     '''check the value of a variable/define'''
345     ret = True
346     v_define = define
347     if v_define is None:
348         v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_')
349     if CHECK_CODE(conf,
350                   'printf("%%u", (unsigned)(%s))' % v,
351                   define=v_define,
352                   execute=True,
353                   define_ret=True,
354                   quote=False,
355                   headers=headers,
356                   local_include=False,
357                   msg="Checking value of %s" % v):
358         return int(conf.env[v_define])
359
360     return None
361
362 @conf
363 def CHECK_CODE(conf, code, define,
364                always=False, execute=False, addmain=True,
365                add_headers=True, mandatory=False,
366                headers=None, msg=None, cflags='', includes='# .',
367                local_include=True, lib=None, link=True,
368                define_ret=False, quote=False,
369                on_target=True, strict=False):
370     '''check if some code compiles and/or runs'''
371
372     if CONFIG_SET(conf, define):
373         return True
374
375     if headers is not None:
376         CHECK_HEADERS(conf, headers=headers, lib=lib)
377
378     if add_headers:
379         hdrs = header_list(conf, headers=headers, lib=lib)
380     else:
381         hdrs = ''
382     if execute:
383         execute = 1
384     else:
385         execute = 0
386
387     if addmain:
388         fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code)
389     else:
390         fragment='%s\n%s\n' % (hdrs, code)
391
392     if msg is None:
393         msg="Checking for %s" % define
394
395     cflags = TO_LIST(cflags)
396
397     # Be strict when relying on a compiler check
398     # Some compilers (e.g. xlc) ignore non-supported features as warnings
399     if strict:
400         extra_cflags = None
401         if conf.env["CC_NAME"] == "gcc":
402             extra_cflags = "-Werror"
403         elif conf.env["CC_NAME"] == "xlc":
404             extra_cflags = "-qhalt=w"
405         cflags.append(extra_cflags)
406
407     if local_include:
408         cflags.append('-I%s' % conf.path.abspath())
409
410     if not link:
411         type='nolink'
412     else:
413         type='cprogram'
414
415     uselib = TO_LIST(lib)
416
417     (ccflags, ldflags, cpppath) = library_flags(conf, uselib)
418
419     includes = TO_LIST(includes)
420     includes.extend(cpppath)
421
422     uselib = [l.upper() for l in uselib]
423
424     cflags.extend(ccflags)
425
426     if on_target:
427         exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
428     else:
429         exec_args = []
430
431     conf.COMPOUND_START(msg)
432
433     try:
434         ret = conf.check(fragment=fragment,
435                      execute=execute,
436                      define_name = define,
437                      cflags=cflags,
438                      ldflags=ldflags,
439                      includes=includes,
440                      uselib=uselib,
441                      type=type,
442                      msg=msg,
443                      quote=quote,
444                      exec_args=exec_args,
445                      define_ret=define_ret)
446     except Exception:
447         if always:
448             conf.DEFINE(define, 0)
449         conf.COMPOUND_END(False)
450         if mandatory:
451             raise
452         return False
453     else:
454         # success
455         if not define_ret:
456             conf.DEFINE(define, 1)
457             conf.COMPOUND_END(True)
458         else:
459             conf.DEFINE(define, ret, quote=quote)
460             conf.COMPOUND_END(ret)
461         return True
462
463
464 @conf
465 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
466                            always=False, define=None, headers=None,
467                            lib=None):
468     '''check for a structure member'''
469     if define is None:
470         define = 'HAVE_%s' % member.upper()
471     return CHECK_CODE(conf,
472                       '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
473                       define,
474                       execute=False,
475                       link=False,
476                       lib=lib,
477                       always=always,
478                       headers=headers,
479                       local_include=False,
480                       msg="Checking for member %s in %s" % (member, structname))
481
482
483 @conf
484 def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n'):
485     '''check if the given cflags are accepted by the compiler
486     '''
487     check_cflags = TO_LIST(cflags)
488     if 'WERROR_CFLAGS' in conf.env:
489         check_cflags.extend(conf.env['WERROR_CFLAGS'])
490     return conf.check(fragment=fragment,
491                       execute=0,
492                       mandatory=False,
493                       type='nolink',
494                       ccflags=check_cflags,
495                       msg="Checking compiler accepts %s" % cflags)
496
497 @conf
498 def CHECK_LDFLAGS(conf, ldflags):
499     '''check if the given ldflags are accepted by the linker
500     '''
501     return conf.check(fragment='int main(void) { return 0; }\n',
502                       execute=0,
503                       ldflags=ldflags,
504                       mandatory=False,
505                       msg="Checking linker accepts %s" % ldflags)
506
507
508 @conf
509 def CONFIG_GET(conf, option):
510     '''return True if a configuration option was found'''
511     if (option in conf.env):
512         return conf.env[option]
513     else:
514         return None
515
516 @conf
517 def CONFIG_SET(conf, option):
518     '''return True if a configuration option was found'''
519     if option not in conf.env:
520         return False
521     v = conf.env[option]
522     if v is None:
523         return False
524     if v == []:
525         return False
526     if v == ():
527         return False
528     return True
529
530 @conf
531 def CONFIG_RESET(conf, option):
532     if option not in conf.env:
533         return
534     del conf.env[option]
535
536 Build.BuildContext.CONFIG_RESET = CONFIG_RESET
537 Build.BuildContext.CONFIG_SET = CONFIG_SET
538 Build.BuildContext.CONFIG_GET = CONFIG_GET
539
540
541 def library_flags(self, libs):
542     '''work out flags from pkg_config'''
543     ccflags = []
544     ldflags = []
545     cpppath = []
546     for lib in TO_LIST(libs):
547         # note that we do not add the -I and -L in here, as that is added by the waf
548         # core. Adding it here would just change the order that it is put on the link line
549         # which can cause system paths to be added before internal libraries
550         extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
551         extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
552         extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
553         ccflags.extend(extra_ccflags)
554         ldflags.extend(extra_ldflags)
555         cpppath.extend(extra_cpppath)
556
557         extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
558         cpppath.extend(extra_cpppath)
559     if 'EXTRA_LDFLAGS' in self.env:
560         ldflags.extend(self.env['EXTRA_LDFLAGS'])
561
562     ccflags = unique_list(ccflags)
563     ldflags = unique_list(ldflags)
564     cpppath = unique_list(cpppath)
565     return (ccflags, ldflags, cpppath)
566
567
568 @conf
569 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
570     '''check if a set of libraries exist as system libraries
571
572     returns the sublist of libs that do exist as a syslib or []
573     '''
574
575     fragment= '''
576 int foo()
577 {
578     int v = 2;
579     return v*2;
580 }
581 '''
582     ret = []
583     liblist  = TO_LIST(libs)
584     for lib in liblist[:]:
585         if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
586             ret.append(lib)
587             continue
588
589         (ccflags, ldflags, cpppath) = library_flags(conf, lib)
590         if shlib:
591             res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
592         else:
593             res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
594
595         if not res:
596             if mandatory:
597                 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
598                 sys.exit(1)
599             if empty_decl:
600                 # if it isn't a mandatory library, then remove it from dependency lists
601                 if set_target:
602                     SET_TARGET_TYPE(conf, lib, 'EMPTY')
603         else:
604             conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
605             conf.env['LIB_' + lib.upper()] = lib
606             if set_target:
607                 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
608             ret.append(lib)
609
610     return ret
611
612
613
614 @conf
615 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
616                    headers=None, link=True, empty_decl=True, set_target=True):
617     """
618     check that the functions in 'list' are available in 'library'
619     if they are, then make that library available as a dependency
620
621     if the library is not available and mandatory==True, then
622     raise an error.
623
624     If the library is not available and mandatory==False, then
625     add the library to the list of dependencies to remove from
626     build rules
627
628     optionally check for the functions first in libc
629     """
630     remaining = TO_LIST(list)
631     liblist   = TO_LIST(library)
632
633     # check if some already found
634     for f in remaining[:]:
635         if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
636             remaining.remove(f)
637
638     # see if the functions are in libc
639     if checklibc:
640         for f in remaining[:]:
641             if CHECK_FUNC(conf, f, link=True, headers=headers):
642                 remaining.remove(f)
643
644     if remaining == []:
645         for lib in liblist:
646             if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
647                 SET_TARGET_TYPE(conf, lib, 'EMPTY')
648         return True
649
650     checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
651     for lib in liblist[:]:
652         if not lib in checklist and mandatory:
653             Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
654             sys.exit(1)
655
656     ret = True
657     for f in remaining:
658         if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
659             ret = False
660
661     return ret
662
663
664 @conf
665 def IN_LAUNCH_DIR(conf):
666     '''return True if this rule is being run from the launch directory'''
667     return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
668 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
669
670
671 @conf
672 def SAMBA_CONFIG_H(conf, path=None):
673     '''write out config.h in the right directory'''
674     # we don't want to produce a config.h in places like lib/replace
675     # when we are building projects that depend on lib/replace
676     if not IN_LAUNCH_DIR(conf):
677         return
678
679     # we need to build real code that can't be optimized away to test
680     stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
681     for stack_protect_flag in stack_protect_list:
682         flag_supported = conf.check(fragment='''
683                                     #include <stdio.h>
684
685                                     int main(void)
686                                     {
687                                         char t[100000];
688                                         while (fgets(t, sizeof(t), stdin));
689                                         return 0;
690                                     }
691                                     ''',
692                                     execute=0,
693                                     ccflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
694                                     mandatory=False,
695                                     msg='Checking if compiler accepts %s' % (stack_protect_flag))
696         if flag_supported:
697             conf.ADD_CFLAGS('-Wp,-D_FORTIFY_SOURCE=2 %s' % (stack_protect_flag))
698             break
699
700     flag_supported = conf.check(fragment='''
701                                 #include <stdio.h>
702
703                                 int main(void)
704                                 {
705                                     char t[100000];
706                                     while (fgets(t, sizeof(t), stdin));
707                                     return 0;
708                                 }
709                                 ''',
710                                 execute=0,
711                                 ccflags=[ '-Werror', '-fstack-clash-protection'],
712                                 mandatory=False,
713                                 msg='Checking if compiler accepts -fstack-clash-protection')
714     if flag_supported:
715         conf.ADD_CFLAGS('-fstack-clash-protection')
716
717     if Options.options.debug:
718         conf.ADD_CFLAGS('-g', testflags=True)
719
720     if Options.options.developer:
721         conf.env.DEVELOPER_MODE = True
722
723         conf.ADD_CFLAGS('-g', testflags=True)
724         conf.ADD_CFLAGS('-Wall', testflags=True)
725         conf.ADD_CFLAGS('-Wshadow', testflags=True)
726         conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
727         conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
728         conf.ADD_CFLAGS('-fno-common', testflags=True)
729
730         conf.ADD_CFLAGS('-Werror=address', testflags=True)
731         # we add these here to ensure that -Wstrict-prototypes is not set during configure
732         conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
733                         testflags=True)
734         conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
735                         testflags=True)
736         conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
737                         testflags=True)
738         conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
739                         testflags=True)
740         conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
741                         testflags=True)
742         conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
743                         testflags=True)
744         conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
745                         testflags=True)
746         conf.ADD_CFLAGS('-Wimplicit-fallthrough',
747                         testflags=True)
748         conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
749                         testflags=True)
750
751         conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
752         conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
753         conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
754                         testflags=True, prereq_flags='-Wformat')
755         # This check is because for ldb_search(), a NULL format string
756         # is not an error, but some compilers complain about that.
757         if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
758 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
759
760 int main(void) {
761         testformat(0);
762         return 0;
763 }
764
765 '''):
766             if not 'EXTRA_CFLAGS' in conf.env:
767                 conf.env['EXTRA_CFLAGS'] = []
768             conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
769
770     if Options.options.picky_developer:
771         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
772         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
773
774     if Options.options.fatal_errors:
775         conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
776
777     if Options.options.pedantic:
778         conf.ADD_CFLAGS('-W', testflags=True)
779
780     if Options.options.address_sanitizer:
781         conf.ADD_CFLAGS('-fno-omit-frame-pointer -O1 -fsanitize=address', testflags=True)
782         conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
783         conf.env['ADDRESS_SANITIZER'] = True
784
785
786     # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
787     # environment variables which are only used the for final build.
788     #
789     # The CFLAGS and LDFLAGS environment variables are also
790     # used for the configure checks which might impact their results.
791     conf.add_os_flags('ADDITIONAL_CFLAGS')
792     if conf.env.ADDITIONAL_CFLAGS and conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS']):
793         conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
794     conf.add_os_flags('ADDITIONAL_LDFLAGS')
795     if conf.env.ADDITIONAL_LDFLAGS and conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS']):
796         conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
797
798     if path is None:
799         conf.write_config_header('default/config.h', top=True, remove=False)
800     else:
801         conf.write_config_header(os.path.join(conf.variant, path), remove=False)
802     for key in conf.env.define_key:
803         conf.undefine(key, from_env=False)
804     conf.env.define_key = []
805     conf.SAMBA_CROSS_CHECK_COMPLETE()
806
807
808 @conf
809 def CONFIG_PATH(conf, name, default):
810     '''setup a configurable path'''
811     if not name in conf.env:
812         if default[0] == '/':
813             conf.env[name] = default
814         else:
815             conf.env[name] = conf.env['PREFIX'] + default
816
817 @conf
818 def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]):
819     '''add some CFLAGS to the command line
820        optionally set testflags to ensure all the flags work
821     '''
822     prereq_flags = TO_LIST(prereq_flags)
823     if testflags:
824         ok_flags=[]
825         for f in flags.split():
826             if CHECK_CFLAGS(conf, [f] + prereq_flags):
827                 ok_flags.append(f)
828         flags = ok_flags
829     if not name in conf.env:
830         conf.env[name] = []
831     conf.env[name].extend(TO_LIST(flags))
832
833 @conf
834 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]):
835     '''add some CFLAGS to the command line
836        optionally set testflags to ensure all the flags work
837     '''
838     ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
839                      prereq_flags=prereq_flags)
840
841 @conf
842 def ADD_LDFLAGS(conf, flags, testflags=False):
843     '''add some LDFLAGS to the command line
844        optionally set testflags to ensure all the flags work
845
846        this will return the flags that are added, if any
847     '''
848     if testflags:
849         ok_flags=[]
850         for f in flags.split():
851             if CHECK_LDFLAGS(conf, f):
852                 ok_flags.append(f)
853         flags = ok_flags
854     if not 'EXTRA_LDFLAGS' in conf.env:
855         conf.env['EXTRA_LDFLAGS'] = []
856     conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
857     return flags
858
859
860 @conf
861 def ADD_EXTRA_INCLUDES(conf, includes):
862     '''add some extra include directories to all builds'''
863     if not 'EXTRA_INCLUDES' in conf.env:
864         conf.env['EXTRA_INCLUDES'] = []
865     conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
866
867
868
869 def CURRENT_CFLAGS(bld, target, cflags, allow_warnings=False, hide_symbols=False):
870     '''work out the current flags. local flags are added first'''
871     ret = TO_LIST(cflags)
872     if not 'EXTRA_CFLAGS' in bld.env:
873         list = []
874     else:
875         list = bld.env['EXTRA_CFLAGS'];
876     ret.extend(list)
877     if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
878         list = bld.env['PICKY_CFLAGS'];
879         ret.extend(list)
880     if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
881         ret.append(bld.env.VISIBILITY_CFLAGS)
882     return ret
883
884
885 @conf
886 def CHECK_CC_ENV(conf):
887     """trim whitespaces from 'CC'.
888     The build farm sometimes puts a space at the start"""
889     if os.environ.get('CC'):
890         conf.env.CC = TO_LIST(os.environ.get('CC'))
891         if len(conf.env.CC) == 1:
892             # make for nicer logs if just a single command
893             conf.env.CC = conf.env.CC[0]
894
895
896 @conf
897 def SETUP_CONFIGURE_CACHE(conf, enable):
898     '''enable/disable cache of configure results'''
899     if enable:
900         # when -C is chosen, we will use a private cache and will
901         # not look into system includes. This roughtly matches what
902         # autoconf does with -C
903         cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
904         mkdir_p(cache_path)
905         Options.cache_global = os.environ['WAFCACHE'] = cache_path
906     else:
907         # when -C is not chosen we will not cache configure checks
908         # We set the recursion limit low to prevent waf from spending
909         # a lot of time on the signatures of the files.
910         Options.cache_global = os.environ['WAFCACHE'] = ''
911         preproc.recursion_limit = 1
912     # in either case we don't need to scan system includes
913     preproc.go_absolute = False
914
915
916 @conf
917 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
918     # we don't want any libraries or modules to rely on runtime
919     # resolution of symbols
920     if not sys.platform.startswith("openbsd"):
921         conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
922
923     if not sys.platform.startswith("openbsd") and conf.env.undefined_ignore_ldflags == []:
924         if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
925             conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']
926