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