6bc34c086f04d66c3eedeb61c3f359af26d8e9e5
[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         # Even when exception happened, conf.check might have set the define
449         # already to int(ret). We want to undefine it in the case of 'always'.
450         # Otherwise, we'd get defines set to 0 when they should be undefined
451         # and it foils #ifdef check
452         if always:
453             conf.undefine(define)
454         conf.COMPOUND_END(False)
455         if mandatory:
456             raise
457         return False
458     else:
459         # Success is indicated by ret but we should unset
460         # defines set by WAF's c_config.check() because it
461         # defines it to int(ret) and we want to undefine it
462         if not ret:
463             conf.undefine(define)
464             conf.COMPOUND_END(False)
465             return False
466         if not define_ret:
467             conf.DEFINE(define, 1)
468             conf.COMPOUND_END(True)
469         else:
470             conf.DEFINE(define, ret, quote=quote)
471             conf.COMPOUND_END(ret)
472         return True
473
474
475 @conf
476 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
477                            always=False, define=None, headers=None,
478                            lib=None):
479     '''check for a structure member'''
480     if define is None:
481         define = 'HAVE_%s' % member.upper()
482     return CHECK_CODE(conf,
483                       '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
484                       define,
485                       execute=False,
486                       link=False,
487                       lib=lib,
488                       always=always,
489                       headers=headers,
490                       local_include=False,
491                       msg="Checking for member %s in %s" % (member, structname))
492
493
494 @conf
495 def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n'):
496     '''check if the given cflags are accepted by the compiler
497     '''
498     check_cflags = TO_LIST(cflags)
499     if 'WERROR_CFLAGS' in conf.env:
500         check_cflags.extend(conf.env['WERROR_CFLAGS'])
501     return conf.check(fragment=fragment,
502                       execute=0,
503                       mandatory=False,
504                       type='nolink',
505                       cflags=check_cflags,
506                       msg="Checking compiler accepts %s" % cflags)
507
508 @conf
509 def CHECK_LDFLAGS(conf, ldflags):
510     '''check if the given ldflags are accepted by the linker
511     '''
512     return conf.check(fragment='int main(void) { return 0; }\n',
513                       execute=0,
514                       ldflags=ldflags,
515                       mandatory=False,
516                       msg="Checking linker accepts %s" % ldflags)
517
518
519 @conf
520 def CONFIG_GET(conf, option):
521     '''return True if a configuration option was found'''
522     if (option in conf.env):
523         return conf.env[option]
524     else:
525         return None
526
527 @conf
528 def CONFIG_SET(conf, option):
529     '''return True if a configuration option was found'''
530     if option not in conf.env:
531         return False
532     v = conf.env[option]
533     if v is None:
534         return False
535     if v == []:
536         return False
537     if v == ():
538         return False
539     return True
540
541 @conf
542 def CONFIG_RESET(conf, option):
543     if option not in conf.env:
544         return
545     del conf.env[option]
546
547 Build.BuildContext.CONFIG_RESET = CONFIG_RESET
548 Build.BuildContext.CONFIG_SET = CONFIG_SET
549 Build.BuildContext.CONFIG_GET = CONFIG_GET
550
551
552 def library_flags(self, libs):
553     '''work out flags from pkg_config'''
554     ccflags = []
555     ldflags = []
556     cpppath = []
557     for lib in TO_LIST(libs):
558         # note that we do not add the -I and -L in here, as that is added by the waf
559         # core. Adding it here would just change the order that it is put on the link line
560         # which can cause system paths to be added before internal libraries
561         extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
562         extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
563         extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
564         ccflags.extend(extra_ccflags)
565         ldflags.extend(extra_ldflags)
566         cpppath.extend(extra_cpppath)
567
568         extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
569         cpppath.extend(extra_cpppath)
570     if 'EXTRA_LDFLAGS' in self.env:
571         ldflags.extend(self.env['EXTRA_LDFLAGS'])
572
573     ccflags = unique_list(ccflags)
574     ldflags = unique_list(ldflags)
575     cpppath = unique_list(cpppath)
576     return (ccflags, ldflags, cpppath)
577
578
579 @conf
580 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
581     '''check if a set of libraries exist as system libraries
582
583     returns the sublist of libs that do exist as a syslib or []
584     '''
585
586     fragment= '''
587 int foo()
588 {
589     int v = 2;
590     return v*2;
591 }
592 '''
593     ret = []
594     liblist  = TO_LIST(libs)
595     for lib in liblist[:]:
596         if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
597             ret.append(lib)
598             continue
599
600         (ccflags, ldflags, cpppath) = library_flags(conf, lib)
601         if shlib:
602             res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
603         else:
604             res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
605
606         if not res:
607             if mandatory:
608                 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
609                 sys.exit(1)
610             if empty_decl:
611                 # if it isn't a mandatory library, then remove it from dependency lists
612                 if set_target:
613                     SET_TARGET_TYPE(conf, lib, 'EMPTY')
614         else:
615             conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
616             conf.env['LIB_' + lib.upper()] = lib
617             if set_target:
618                 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
619             ret.append(lib)
620
621     return ret
622
623
624
625 @conf
626 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
627                    headers=None, link=True, empty_decl=True, set_target=True):
628     """
629     check that the functions in 'list' are available in 'library'
630     if they are, then make that library available as a dependency
631
632     if the library is not available and mandatory==True, then
633     raise an error.
634
635     If the library is not available and mandatory==False, then
636     add the library to the list of dependencies to remove from
637     build rules
638
639     optionally check for the functions first in libc
640     """
641     remaining = TO_LIST(list)
642     liblist   = TO_LIST(library)
643
644     # check if some already found
645     for f in remaining[:]:
646         if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
647             remaining.remove(f)
648
649     # see if the functions are in libc
650     if checklibc:
651         for f in remaining[:]:
652             if CHECK_FUNC(conf, f, link=True, headers=headers):
653                 remaining.remove(f)
654
655     if remaining == []:
656         for lib in liblist:
657             if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
658                 SET_TARGET_TYPE(conf, lib, 'EMPTY')
659         return True
660
661     checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
662     for lib in liblist[:]:
663         if not lib in checklist and mandatory:
664             Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
665             sys.exit(1)
666
667     ret = True
668     for f in remaining:
669         if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
670             ret = False
671
672     return ret
673
674
675 @conf
676 def IN_LAUNCH_DIR(conf):
677     '''return True if this rule is being run from the launch directory'''
678     return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
679 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
680
681
682 @conf
683 def SAMBA_CONFIG_H(conf, path=None):
684     '''write out config.h in the right directory'''
685     # we don't want to produce a config.h in places like lib/replace
686     # when we are building projects that depend on lib/replace
687     if not IN_LAUNCH_DIR(conf):
688         return
689
690     # we need to build real code that can't be optimized away to test
691     stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
692     for stack_protect_flag in stack_protect_list:
693         flag_supported = conf.check(fragment='''
694                                     #include <stdio.h>
695
696                                     int main(void)
697                                     {
698                                         char t[100000];
699                                         while (fgets(t, sizeof(t), stdin));
700                                         return 0;
701                                     }
702                                     ''',
703                                     execute=0,
704                                     cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
705                                     mandatory=False,
706                                     msg='Checking if compiler accepts %s' % (stack_protect_flag))
707         if flag_supported:
708             conf.ADD_CFLAGS('-Wp,-D_FORTIFY_SOURCE=2 %s' % (stack_protect_flag))
709             break
710
711     flag_supported = conf.check(fragment='''
712                                 #include <stdio.h>
713
714                                 int main(void)
715                                 {
716                                     char t[100000];
717                                     while (fgets(t, sizeof(t), stdin));
718                                     return 0;
719                                 }
720                                 ''',
721                                 execute=0,
722                                 cflags=[ '-Werror', '-fstack-clash-protection'],
723                                 mandatory=False,
724                                 msg='Checking if compiler accepts -fstack-clash-protection')
725     if flag_supported:
726         conf.ADD_CFLAGS('-fstack-clash-protection')
727
728     if Options.options.debug:
729         conf.ADD_CFLAGS('-g', testflags=True)
730
731     if Options.options.developer:
732         conf.env.DEVELOPER_MODE = True
733
734         conf.ADD_CFLAGS('-g', testflags=True)
735         conf.ADD_CFLAGS('-Wall', testflags=True)
736         conf.ADD_CFLAGS('-Wshadow', testflags=True)
737         conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
738         conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
739         conf.ADD_CFLAGS('-fno-common', testflags=True)
740
741         conf.ADD_CFLAGS('-Werror=address', testflags=True)
742         # we add these here to ensure that -Wstrict-prototypes is not set during configure
743         conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
744                         testflags=True)
745         conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
746                         testflags=True)
747         conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
748                         testflags=True)
749         conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
750                         testflags=True)
751         conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
752                         testflags=True)
753         conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
754                         testflags=True)
755         conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
756                         testflags=True)
757         conf.ADD_CFLAGS('-Wimplicit-fallthrough',
758                         testflags=True)
759         conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
760                         testflags=True)
761
762         conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
763         conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
764         conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
765                         testflags=True, prereq_flags='-Wformat')
766         # This check is because for ldb_search(), a NULL format string
767         # is not an error, but some compilers complain about that.
768         if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
769 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
770
771 int main(void) {
772         testformat(0);
773         return 0;
774 }
775
776 '''):
777             if not 'EXTRA_CFLAGS' in conf.env:
778                 conf.env['EXTRA_CFLAGS'] = []
779             conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
780
781     if Options.options.picky_developer:
782         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
783         conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
784
785     if Options.options.fatal_errors:
786         conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
787
788     if Options.options.pedantic:
789         conf.ADD_CFLAGS('-W', testflags=True)
790
791     if Options.options.address_sanitizer:
792         conf.ADD_CFLAGS('-fno-omit-frame-pointer -O1 -fsanitize=address', testflags=True)
793         conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
794         conf.env['ADDRESS_SANITIZER'] = True
795
796
797     # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
798     # environment variables which are only used the for final build.
799     #
800     # The CFLAGS and LDFLAGS environment variables are also
801     # used for the configure checks which might impact their results.
802     conf.add_os_flags('ADDITIONAL_CFLAGS')
803     if conf.env.ADDITIONAL_CFLAGS and conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS']):
804         conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
805     conf.add_os_flags('ADDITIONAL_LDFLAGS')
806     if conf.env.ADDITIONAL_LDFLAGS and conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS']):
807         conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
808
809     if path is None:
810         conf.write_config_header('default/config.h', top=True, remove=False)
811     else:
812         conf.write_config_header(os.path.join(conf.variant, path), remove=False)
813     for key in conf.env.define_key:
814         conf.undefine(key, from_env=False)
815     conf.env.define_key = []
816     conf.SAMBA_CROSS_CHECK_COMPLETE()
817
818
819 @conf
820 def CONFIG_PATH(conf, name, default):
821     '''setup a configurable path'''
822     if not name in conf.env:
823         if default[0] == '/':
824             conf.env[name] = default
825         else:
826             conf.env[name] = conf.env['PREFIX'] + default
827
828 @conf
829 def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]):
830     '''add some CFLAGS to the command line
831        optionally set testflags to ensure all the flags work
832     '''
833     prereq_flags = TO_LIST(prereq_flags)
834     if testflags:
835         ok_flags=[]
836         for f in flags.split():
837             if CHECK_CFLAGS(conf, [f] + prereq_flags):
838                 ok_flags.append(f)
839         flags = ok_flags
840     if not name in conf.env:
841         conf.env[name] = []
842     conf.env[name].extend(TO_LIST(flags))
843
844 @conf
845 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]):
846     '''add some CFLAGS to the command line
847        optionally set testflags to ensure all the flags work
848     '''
849     ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
850                      prereq_flags=prereq_flags)
851
852 @conf
853 def ADD_LDFLAGS(conf, flags, testflags=False):
854     '''add some LDFLAGS to the command line
855        optionally set testflags to ensure all the flags work
856
857        this will return the flags that are added, if any
858     '''
859     if testflags:
860         ok_flags=[]
861         for f in flags.split():
862             if CHECK_LDFLAGS(conf, f):
863                 ok_flags.append(f)
864         flags = ok_flags
865     if not 'EXTRA_LDFLAGS' in conf.env:
866         conf.env['EXTRA_LDFLAGS'] = []
867     conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
868     return flags
869
870
871 @conf
872 def ADD_EXTRA_INCLUDES(conf, includes):
873     '''add some extra include directories to all builds'''
874     if not 'EXTRA_INCLUDES' in conf.env:
875         conf.env['EXTRA_INCLUDES'] = []
876     conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
877
878
879
880 def CURRENT_CFLAGS(bld, target, cflags, allow_warnings=False, hide_symbols=False):
881     '''work out the current flags. local flags are added first'''
882     ret = TO_LIST(cflags)
883     if not 'EXTRA_CFLAGS' in bld.env:
884         list = []
885     else:
886         list = bld.env['EXTRA_CFLAGS'];
887     ret.extend(list)
888     if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
889         list = bld.env['PICKY_CFLAGS'];
890         ret.extend(list)
891     if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
892         ret.append(bld.env.VISIBILITY_CFLAGS)
893     return ret
894
895
896 @conf
897 def CHECK_CC_ENV(conf):
898     """trim whitespaces from 'CC'.
899     The build farm sometimes puts a space at the start"""
900     if os.environ.get('CC'):
901         conf.env.CC = TO_LIST(os.environ.get('CC'))
902         if len(conf.env.CC) == 1:
903             # make for nicer logs if just a single command
904             conf.env.CC = conf.env.CC[0]
905
906
907 @conf
908 def SETUP_CONFIGURE_CACHE(conf, enable):
909     '''enable/disable cache of configure results'''
910     if enable:
911         # when -C is chosen, we will use a private cache and will
912         # not look into system includes. This roughtly matches what
913         # autoconf does with -C
914         cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
915         mkdir_p(cache_path)
916         Options.cache_global = os.environ['WAFCACHE'] = cache_path
917     else:
918         # when -C is not chosen we will not cache configure checks
919         # We set the recursion limit low to prevent waf from spending
920         # a lot of time on the signatures of the files.
921         Options.cache_global = os.environ['WAFCACHE'] = ''
922         preproc.recursion_limit = 1
923     # in either case we don't need to scan system includes
924     preproc.go_absolute = False
925
926
927 @conf
928 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
929     # we don't want any libraries or modules to rely on runtime
930     # resolution of symbols
931     if not sys.platform.startswith("openbsd"):
932         conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
933
934     if not sys.platform.startswith("openbsd") and conf.env.undefined_ignore_ldflags == []:
935         if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
936             conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']
937