selftest: enable undefined behaviour sanitizer
[bbaumbach/samba-autobuild/.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; }\n' % 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     in_lib_str = ""
255     if lib:
256         in_lib_str = " in %s" % lib
257     conf.COMPOUND_START('Checking for %s%s' % (f, in_lib_str))
258
259     if link is None or link:
260         ret = CHECK_CODE(conf,
261                          # this is based on the autoconf strategy
262                          '''
263                          #define %s __fake__%s
264                          #ifdef HAVE_LIMITS_H
265                          # include <limits.h>
266                          #else
267                          # include <assert.h>
268                          #endif
269                          #undef %s
270                          #if defined __stub_%s || defined __stub___%s
271                          #error "bad glibc stub"
272                          #endif
273                          extern char %s();
274                          int main() { return %s(); }
275                          ''' % (f, f, f, f, f, f, f),
276                          execute=False,
277                          link=True,
278                          addmain=False,
279                          add_headers=False,
280                          define=define,
281                          local_include=False,
282                          lib=lib,
283                          headers=headers,
284                          msg='Checking for %s' % f)
285
286         if not ret:
287             ret = CHECK_CODE(conf,
288                              # it might be a macro
289                              # we need to make sure the compiler doesn't
290                              # optimize it out...
291                              'void *__x = (void *)%s; return (int)__x' % f,
292                              execute=False,
293                              link=True,
294                              addmain=True,
295                              add_headers=True,
296                              define=define,
297                              local_include=False,
298                              lib=lib,
299                              headers=headers,
300                              msg='Checking for macro %s' % f)
301
302     if not ret and (link is None or not link):
303         ret = CHECK_VARIABLE(conf, f,
304                              define=define,
305                              headers=headers,
306                              msg='Checking for declaration of %s' % f)
307     conf.COMPOUND_END(ret)
308     return ret
309
310
311 @conf
312 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
313     '''check for a list of functions'''
314     ret = True
315     for f in TO_LIST(list):
316         if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
317             ret = False
318     return ret
319
320
321 @conf
322 def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True):
323     '''check the size of a type'''
324     for v in TO_LIST(vars):
325         v_define = define
326         ret = False
327         if v_define is None:
328             v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
329         for size in list((1, 2, 4, 8, 16, 32, 64)):
330             if CHECK_CODE(conf,
331                       'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size),
332                       define=v_define,
333                       quote=False,
334                       headers=headers,
335                       local_include=False,
336                       msg="Checking if size of %s == %d" % (v, size)):
337                 conf.DEFINE(v_define, size)
338                 ret = True
339                 break
340         if not ret and critical:
341             Logs.error("Couldn't determine size of '%s'" % v)
342             sys.exit(1)
343     return ret
344
345 @conf
346 def CHECK_VALUEOF(conf, v, headers=None, define=None):
347     '''check the value of a variable/define'''
348     ret = True
349     v_define = define
350     if v_define is None:
351         v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_')
352     if CHECK_CODE(conf,
353                   'printf("%%u", (unsigned)(%s))' % v,
354                   define=v_define,
355                   execute=True,
356                   define_ret=True,
357                   quote=False,
358                   headers=headers,
359                   local_include=False,
360                   msg="Checking value of %s" % v):
361         return int(conf.env[v_define])
362
363     return None
364
365 @conf
366 def CHECK_CODE(conf, code, define,
367                always=False, execute=False, addmain=True,
368                add_headers=True, mandatory=False,
369                headers=None, msg=None, cflags='', includes='# .',
370                local_include=True, lib=None, link=True,
371                define_ret=False, quote=False,
372                on_target=True, strict=False):
373     '''check if some code compiles and/or runs'''
374
375     if CONFIG_SET(conf, define):
376         return True
377
378     if headers is not None:
379         CHECK_HEADERS(conf, headers=headers, lib=lib)
380
381     if add_headers:
382         hdrs = header_list(conf, headers=headers, lib=lib)
383     else:
384         hdrs = ''
385     if execute:
386         execute = 1
387     else:
388         execute = 0
389
390     if addmain:
391         fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code)
392     else:
393         fragment='%s\n%s\n' % (hdrs, code)
394
395     if msg is None:
396         msg="Checking for %s" % define
397
398     cflags = TO_LIST(cflags)
399
400     # Be strict when relying on a compiler check
401     # Some compilers (e.g. xlc) ignore non-supported features as warnings
402     if strict:
403         if 'WERROR_CFLAGS' in conf.env:
404             cflags.extend(conf.env['WERROR_CFLAGS'])
405
406     if local_include:
407         cflags.append('-I%s' % conf.path.abspath())
408
409     if not link:
410         type='nolink'
411     else:
412         type='cprogram'
413
414     uselib = TO_LIST(lib)
415
416     (ccflags, ldflags, cpppath) = library_flags(conf, uselib)
417
418     includes = TO_LIST(includes)
419     includes.extend(cpppath)
420
421     uselib = [l.upper() for l in uselib]
422
423     cflags.extend(ccflags)
424
425     if on_target:
426         exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
427     else:
428         exec_args = []
429
430     conf.COMPOUND_START(msg)
431
432     try:
433         ret = conf.check(fragment=fragment,
434                      execute=execute,
435                      define_name = define,
436                      cflags=cflags,
437                      ldflags=ldflags,
438                      includes=includes,
439                      uselib=uselib,
440                      type=type,
441                      msg=msg,
442                      quote=quote,
443                      exec_args=exec_args,
444                      define_ret=define_ret)
445     except Exception:
446         if always:
447             conf.DEFINE(define, 0)
448         else:
449             conf.undefine(define)
450         conf.COMPOUND_END(False)
451         if mandatory:
452             raise
453         return False
454     else:
455         # Success is indicated by ret but we should unset
456         # defines set by WAF's c_config.check() because it
457         # defines it to int(ret) and we want to undefine it
458         if not ret:
459             conf.undefine(define)
460             conf.COMPOUND_END(False)
461             return False
462         if not define_ret:
463             conf.DEFINE(define, 1)
464             conf.COMPOUND_END(True)
465         else:
466             conf.DEFINE(define, ret, quote=quote)
467             conf.COMPOUND_END(ret)
468         return True
469
470
471 @conf
472 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
473                            always=False, define=None, headers=None,
474                            lib=None):
475     '''check for a structure member'''
476     if define is None:
477         define = 'HAVE_%s' % member.upper()
478     return CHECK_CODE(conf,
479                       '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
480                       define,
481                       execute=False,
482                       link=False,
483                       lib=lib,
484                       always=always,
485                       headers=headers,
486                       local_include=False,
487                       msg="Checking for member %s in %s" % (member, structname))
488
489
490 @conf
491 def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n'):
492     '''check if the given cflags are accepted by the compiler
493     '''
494     check_cflags = TO_LIST(cflags)
495     if 'WERROR_CFLAGS' in conf.env:
496         check_cflags.extend(conf.env['WERROR_CFLAGS'])
497     return conf.check(fragment=fragment,
498                       execute=0,
499                       mandatory=False,
500                       type='nolink',
501                       cflags=check_cflags,
502                       msg="Checking compiler accepts %s" % cflags)
503
504 @conf
505 def CHECK_LDFLAGS(conf, ldflags):
506     '''check if the given ldflags are accepted by the linker
507     '''
508     return conf.check(fragment='int main(void) { return 0; }\n',
509                       execute=0,
510                       ldflags=ldflags,
511                       mandatory=False,
512                       msg="Checking linker accepts %s" % ldflags)
513
514
515 @conf
516 def CONFIG_GET(conf, option):
517     '''return True if a configuration option was found'''
518     if (option in conf.env):
519         return conf.env[option]
520     else:
521         return None
522
523 @conf
524 def CONFIG_SET(conf, option):
525     '''return True if a configuration option was found'''
526     if option not in conf.env:
527         return False
528     v = conf.env[option]
529     if v is None:
530         return False
531     if v == []:
532         return False
533     if v == ():
534         return False
535     return True
536
537 @conf
538 def CONFIG_RESET(conf, option):
539     if option not in conf.env:
540         return
541     del conf.env[option]
542
543 Build.BuildContext.CONFIG_RESET = CONFIG_RESET
544 Build.BuildContext.CONFIG_SET = CONFIG_SET
545 Build.BuildContext.CONFIG_GET = CONFIG_GET
546
547
548 def library_flags(self, libs):
549     '''work out flags from pkg_config'''
550     ccflags = []
551     ldflags = []
552     cpppath = []
553     for lib in TO_LIST(libs):
554         # note that we do not add the -I and -L in here, as that is added by the waf
555         # core. Adding it here would just change the order that it is put on the link line
556         # which can cause system paths to be added before internal libraries
557         extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
558         extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
559         extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
560         ccflags.extend(extra_ccflags)
561         ldflags.extend(extra_ldflags)
562         cpppath.extend(extra_cpppath)
563
564         extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
565         cpppath.extend(extra_cpppath)
566     if 'EXTRA_LDFLAGS' in self.env:
567         ldflags.extend(self.env['EXTRA_LDFLAGS'])
568
569     ccflags = unique_list(ccflags)
570     ldflags = unique_list(ldflags)
571     cpppath = unique_list(cpppath)
572     return (ccflags, ldflags, cpppath)
573
574
575 @conf
576 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
577     '''check if a set of libraries exist as system libraries
578
579     returns the sublist of libs that do exist as a syslib or []
580     '''
581
582     fragment= '''
583 int foo()
584 {
585     int v = 2;
586     return v*2;
587 }
588 '''
589     ret = []
590     liblist  = TO_LIST(libs)
591     for lib in liblist[:]:
592         if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
593             ret.append(lib)
594             continue
595
596         (ccflags, ldflags, cpppath) = library_flags(conf, lib)
597         if shlib:
598             res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
599         else:
600             res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
601
602         if not res:
603             if mandatory:
604                 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
605                 sys.exit(1)
606             if empty_decl:
607                 # if it isn't a mandatory library, then remove it from dependency lists
608                 if set_target:
609                     SET_TARGET_TYPE(conf, lib, 'EMPTY')
610         else:
611             conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
612             conf.env['LIB_' + lib.upper()] = lib
613             if set_target:
614                 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
615             ret.append(lib)
616
617     return ret
618
619
620
621 @conf
622 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
623                    headers=None, link=True, empty_decl=True, set_target=True):
624     """
625     check that the functions in 'list' are available in 'library'
626     if they are, then make that library available as a dependency
627
628     if the library is not available and mandatory==True, then
629     raise an error.
630
631     If the library is not available and mandatory==False, then
632     add the library to the list of dependencies to remove from
633     build rules
634
635     optionally check for the functions first in libc
636     """
637     remaining = TO_LIST(list)
638     liblist   = TO_LIST(library)
639
640     # check if some already found
641     for f in remaining[:]:
642         if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
643             remaining.remove(f)
644
645     # see if the functions are in libc
646     if checklibc:
647         for f in remaining[:]:
648             if CHECK_FUNC(conf, f, link=True, headers=headers):
649                 remaining.remove(f)
650
651     if remaining == []:
652         for lib in liblist:
653             if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
654                 SET_TARGET_TYPE(conf, lib, 'EMPTY')
655         return True
656
657     checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
658     for lib in liblist[:]:
659         if not lib in checklist and mandatory:
660             Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
661             sys.exit(1)
662
663     ret = True
664     for f in remaining:
665         if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
666             ret = False
667
668     return ret
669
670
671 @conf
672 def IN_LAUNCH_DIR(conf):
673     '''return True if this rule is being run from the launch directory'''
674     return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
675 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
676
677
678 @conf
679 def SAMBA_CONFIG_H(conf, path=None):
680     '''write out config.h in the right directory'''
681     # we don't want to produce a config.h in places like lib/replace
682     # when we are building projects that depend on lib/replace
683     if not IN_LAUNCH_DIR(conf):
684         return
685
686     # we need to build real code that can't be optimized away to test
687     stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
688     for stack_protect_flag in stack_protect_list:
689         flag_supported = conf.check(fragment='''
690                                     #include <stdio.h>
691
692                                     int main(void)
693                                     {
694                                         char t[100000];
695                                         while (fgets(t, sizeof(t), stdin));
696                                         return 0;
697                                     }
698                                     ''',
699                                     execute=0,
700                                     cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
701                                     mandatory=False,
702                                     msg='Checking if compiler accepts %s' % (stack_protect_flag))
703         if flag_supported:
704             conf.ADD_CFLAGS('%s' % (stack_protect_flag))
705             break
706
707     flag_supported = conf.check(fragment='''
708                                 #include <stdio.h>
709
710                                 int main(void)
711                                 {
712                                     char t[100000];
713                                     while (fgets(t, sizeof(t), stdin));
714                                     return 0;
715                                 }
716                                 ''',
717                                 execute=0,
718                                 cflags=[ '-Werror', '-fstack-clash-protection'],
719                                 mandatory=False,
720                                 msg='Checking if compiler accepts -fstack-clash-protection')
721     if flag_supported:
722         conf.ADD_CFLAGS('-fstack-clash-protection')
723
724     if Options.options.debug:
725         conf.ADD_CFLAGS('-g', testflags=True)
726
727     if Options.options.developer:
728         conf.env.DEVELOPER_MODE = True
729
730         conf.ADD_CFLAGS('-g', testflags=True)
731         conf.ADD_CFLAGS('-Wall', testflags=True)
732         conf.ADD_CFLAGS('-Wshadow', testflags=True)
733         conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
734         if CHECK_CODE(conf,
735                       'struct a { int b; }; struct c { struct a d; } e = { };',
736                       'CHECK_C99_INIT',
737                       link=False,
738                       cflags='-Wmissing-field-initializers -Werror=missing-field-initializers',
739                       msg="Checking C99 init of nested structs."):
740             conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True)
741         conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True)
742         conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True)
743         conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
744         conf.ADD_CFLAGS('-fno-common', testflags=True)
745
746         conf.ADD_CFLAGS('-Werror=address', testflags=True)
747         # we add these here to ensure that -Wstrict-prototypes is not set during configure
748         conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
749                         testflags=True)
750         conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
751                         testflags=True)
752         conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
753                         testflags=True)
754         conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
755                         testflags=True)
756         conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
757                         testflags=True)
758         conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
759                         testflags=True)
760         conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
761                         testflags=True)
762         conf.ADD_CFLAGS('-Wimplicit-fallthrough',
763                         testflags=True)
764         conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
765                         testflags=True)
766
767         conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
768         conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
769         conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
770                         testflags=True, prereq_flags='-Wformat')
771         # This check is because for ldb_search(), a NULL format string
772         # is not an error, but some compilers complain about that.
773         if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
774 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
775
776 int main(void) {
777         testformat(0);
778         return 0;
779 }
780
781 '''):
782             if not 'EXTRA_CFLAGS' in conf.env:
783                 conf.env['EXTRA_CFLAGS'] = []
784             conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
785
786     if Options.options.picky_developer:
787         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
788         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
789
790     if Options.options.fatal_errors:
791         conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
792
793     if Options.options.pedantic:
794         conf.ADD_CFLAGS('-W', testflags=True)
795
796     if (Options.options.address_sanitizer or
797         Options.options.undefined_sanitizer):
798         conf.ADD_CFLAGS('-fno-omit-frame-pointer -O1', testflags=True)
799     if Options.options.address_sanitizer:
800         conf.ADD_CFLAGS('-fsanitize=address', testflags=True)
801         conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
802         conf.env['ADDRESS_SANITIZER'] = True
803     if Options.options.undefined_sanitizer:
804         conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True)
805         conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True)
806         conf.env['UNDEFINED_SANITIZER'] = True
807
808
809     # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
810     # environment variables which are only used the for final build.
811     #
812     # The CFLAGS and LDFLAGS environment variables are also
813     # used for the configure checks which might impact their results.
814     conf.add_os_flags('ADDITIONAL_CFLAGS')
815     if conf.env.ADDITIONAL_CFLAGS and conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS']):
816         conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
817     conf.add_os_flags('ADDITIONAL_LDFLAGS')
818     if conf.env.ADDITIONAL_LDFLAGS and conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS']):
819         conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
820
821     if path is None:
822         conf.write_config_header('default/config.h', top=True, remove=False)
823     else:
824         conf.write_config_header(os.path.join(conf.variant, path), remove=False)
825     for key in conf.env.define_key:
826         conf.undefine(key, from_env=False)
827     conf.env.define_key = []
828     conf.SAMBA_CROSS_CHECK_COMPLETE()
829
830
831 @conf
832 def CONFIG_PATH(conf, name, default):
833     '''setup a configurable path'''
834     if not name in conf.env:
835         if default[0] == '/':
836             conf.env[name] = default
837         else:
838             conf.env[name] = conf.env['PREFIX'] + default
839
840 @conf
841 def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]):
842     '''add some CFLAGS to the command line
843        optionally set testflags to ensure all the flags work
844     '''
845     prereq_flags = TO_LIST(prereq_flags)
846     if testflags:
847         ok_flags=[]
848         for f in flags.split():
849             if CHECK_CFLAGS(conf, [f] + prereq_flags):
850                 ok_flags.append(f)
851         flags = ok_flags
852     if not name in conf.env:
853         conf.env[name] = []
854     conf.env[name].extend(TO_LIST(flags))
855
856 @conf
857 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]):
858     '''add some CFLAGS to the command line
859        optionally set testflags to ensure all the flags work
860     '''
861     ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
862                      prereq_flags=prereq_flags)
863
864 @conf
865 def ADD_LDFLAGS(conf, flags, testflags=False):
866     '''add some LDFLAGS to the command line
867        optionally set testflags to ensure all the flags work
868
869        this will return the flags that are added, if any
870     '''
871     if testflags:
872         ok_flags=[]
873         for f in flags.split():
874             if CHECK_LDFLAGS(conf, f):
875                 ok_flags.append(f)
876         flags = ok_flags
877     if not 'EXTRA_LDFLAGS' in conf.env:
878         conf.env['EXTRA_LDFLAGS'] = []
879     conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
880     return flags
881
882
883 @conf
884 def ADD_EXTRA_INCLUDES(conf, includes):
885     '''add some extra include directories to all builds'''
886     if not 'EXTRA_INCLUDES' in conf.env:
887         conf.env['EXTRA_INCLUDES'] = []
888     conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
889
890
891
892 def CURRENT_CFLAGS(bld, target, cflags, allow_warnings=False, hide_symbols=False):
893     '''work out the current flags. local flags are added first'''
894     ret = TO_LIST(cflags)
895     if not 'EXTRA_CFLAGS' in bld.env:
896         list = []
897     else:
898         list = bld.env['EXTRA_CFLAGS'];
899     ret.extend(list)
900     if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
901         list = bld.env['PICKY_CFLAGS'];
902         ret.extend(list)
903     if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
904         ret.append(bld.env.VISIBILITY_CFLAGS)
905     return ret
906
907
908 @conf
909 def CHECK_CC_ENV(conf):
910     """trim whitespaces from 'CC'.
911     The build farm sometimes puts a space at the start"""
912     if os.environ.get('CC'):
913         conf.env.CC = TO_LIST(os.environ.get('CC'))
914
915
916 @conf
917 def SETUP_CONFIGURE_CACHE(conf, enable):
918     '''enable/disable cache of configure results'''
919     if enable:
920         # when -C is chosen, we will use a private cache and will
921         # not look into system includes. This roughtly matches what
922         # autoconf does with -C
923         cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
924         mkdir_p(cache_path)
925         Options.cache_global = os.environ['WAFCACHE'] = cache_path
926     else:
927         # when -C is not chosen we will not cache configure checks
928         # We set the recursion limit low to prevent waf from spending
929         # a lot of time on the signatures of the files.
930         Options.cache_global = os.environ['WAFCACHE'] = ''
931         preproc.recursion_limit = 1
932     # in either case we don't need to scan system includes
933     preproc.go_absolute = False
934
935
936 @conf
937 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
938     if not sys.platform.startswith("openbsd"):
939         # we don't want any libraries or modules to rely on runtime
940         # resolution of symbols
941         conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
942
943         if (conf.env.undefined_ignore_ldflags == [] and
944             conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'])):
945             conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']