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