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