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