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