s3: smbd: Deliberately currupt an uninitialized pointer.
[Samba.git] / buildtools / wafsamba / samba_autoconf.py
blob8541d003e2a5b2274c5c31702a7ce70fe905d7eb
1 # a waf tool to add autoconf-like macros to the configure section
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
10 missing_headers = set()
12 ####################################################
13 # some autoconf like helpers, to make the transition
14 # to waf a bit easier for those used to autoconf
15 # m4 files
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)))
24 def hlist_to_string(conf, headers=None):
25 '''convert a headers list to a set of #include lines'''
26 hlist = conf.env.hlist
27 if headers:
28 hlist = hlist[:]
29 hlist.extend(TO_LIST(headers))
30 hdrs = "\n".join('#include <%s>' % h for h in hlist)
32 return hdrs
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
43 v = getattr(conf.env, 'in_compound', [])
44 if v != [] and v != 0:
45 conf.env.in_compound = v + 1
46 return
47 conf.start_msg(msg)
48 conf.saved_check_message_1 = conf.start_msg
49 conf.start_msg = null_check_message_1
50 conf.saved_check_message_2 = conf.end_msg
51 conf.end_msg = null_check_message_2
52 conf.env.in_compound = 1
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.start_msg = conf.saved_check_message_1
62 conf.end_msg = conf.saved_check_message_2
63 p = conf.end_msg
64 if result is True:
65 p('ok')
66 elif not result:
67 p('not found', 'YELLOW')
68 else:
69 p(result)
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
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
94 (ccflags, ldflags, cpppath) = library_flags(conf, lib)
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; }\n' % hdrs,
100 type='nolink',
101 execute=0,
102 cflags=ccflags,
103 mandatory=False,
104 includes=cpppath,
105 uselib=lib.upper(),
106 msg="Checking for header %s" % h)
107 if not ret:
108 missing_headers.add(h)
109 return False
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
117 @conf
118 def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None):
119 '''check for a list of headers
121 when together==True, then the headers accumulate within this test.
122 This is useful for interdependent headers
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
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)
148 @conf
149 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None, cflags=''):
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 cflags=cflags,
162 lib=lib,
163 link=False)
164 if not ret and alternate:
165 conf.DEFINE(t, alternate)
166 return ret
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
180 @conf
181 def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None, cflags=''):
182 '''check for a single type with a header'''
183 return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define, cflags=cflags)
186 @conf
187 def CHECK_VARIABLE(conf, v, define=None, always=False,
188 headers=None, msg=None, lib=None,
189 mandatory=False):
190 '''check for a variable declaration (or define)'''
191 if define is None:
192 define = 'HAVE_%s' % v.upper()
194 if msg is None:
195 msg="Checking for variable %s" % v
197 return CHECK_CODE(conf,
198 # we need to make sure the compiler doesn't
199 # optimize it out...
201 #ifndef %s
202 void *_x; _x=(void *)&%s; return (int)_x;
203 #endif
204 return 0
205 ''' % (v, v),
206 execute=False,
207 link=False,
208 msg=msg,
209 local_include=False,
210 lib=lib,
211 headers=headers,
212 define=define,
213 mandatory=mandatory,
214 always=always)
217 @conf
218 def CHECK_DECLS(conf, vars, reverse=False, headers=None, lib=None, always=False):
219 '''check a list of variable declarations, using the HAVE_DECL_xxx form
220 of define
222 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
224 ret = True
225 for v in TO_LIST(vars):
226 if not reverse:
227 define='HAVE_DECL_%s' % v.upper()
228 else:
229 define='HAVE_%s_DECL' % v.upper()
230 if not CHECK_VARIABLE(conf, v,
231 define=define,
232 headers=headers,
233 lib=lib,
234 msg='Checking for declaration of %s' % v,
235 always=always):
236 if not CHECK_CODE(conf,
238 return (int)%s;
239 ''' % (v),
240 execute=False,
241 link=False,
242 msg='Checking for declaration of %s (as enum)' % v,
243 local_include=False,
244 headers=headers,
245 lib=lib,
246 define=define,
247 always=always):
248 ret = False
249 return ret
252 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
253 '''check for a function'''
254 define='HAVE_%s' % f.upper()
256 ret = False
258 in_lib_str = ""
259 if lib:
260 in_lib_str = " in %s" % lib
261 conf.COMPOUND_START('Checking for %s%s' % (f, in_lib_str))
263 if link is None or link:
264 ret = CHECK_CODE(conf,
265 # this is based on the autoconf strategy
267 #define %s __fake__%s
268 #ifdef HAVE_LIMITS_H
269 # include <limits.h>
270 #else
271 # include <assert.h>
272 #endif
273 #undef %s
274 #if defined __stub_%s || defined __stub___%s
275 #error "bad glibc stub"
276 #endif
277 extern char %s();
278 int main() { return %s(); }
279 ''' % (f, f, f, f, f, f, f),
280 execute=False,
281 link=True,
282 addmain=False,
283 add_headers=False,
284 define=define,
285 local_include=False,
286 lib=lib,
287 headers=headers,
288 msg='Checking for %s' % f)
290 if not ret:
291 ret = CHECK_CODE(conf,
292 # it might be a macro
293 # we need to make sure the compiler doesn't
294 # optimize it out...
295 'void *__x = (void *)%s; return (int)__x' % f,
296 execute=False,
297 link=True,
298 addmain=True,
299 add_headers=True,
300 define=define,
301 local_include=False,
302 lib=lib,
303 headers=headers,
304 msg='Checking for macro %s' % f)
306 if not ret and (link is None or not link):
307 ret = CHECK_VARIABLE(conf, f,
308 define=define,
309 headers=headers,
310 msg='Checking for declaration of %s' % f)
311 conf.COMPOUND_END(ret)
312 return ret
315 @conf
316 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
317 '''check for a list of functions'''
318 ret = True
319 for f in TO_LIST(list):
320 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
321 ret = False
322 return ret
325 @conf
326 def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True):
327 '''check the size of a type'''
328 for v in TO_LIST(vars):
329 v_define = define
330 ret = False
331 if v_define is None:
332 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
333 for size in list((1, 2, 4, 8, 16, 32, 64)):
334 if CHECK_CODE(conf,
335 'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size),
336 define=v_define,
337 quote=False,
338 headers=headers,
339 local_include=False,
340 msg="Checking if size of %s == %d" % (v, size)):
341 conf.DEFINE(v_define, size)
342 ret = True
343 break
344 if not ret and critical:
345 Logs.error("Couldn't determine size of '%s'" % v)
346 sys.exit(1)
347 return ret
349 @conf
350 def CHECK_SIGN(conf, v, headers=None):
351 '''check the sign of a type'''
352 define_name = v.upper().replace(' ', '_')
353 for op, signed in [('<', 'signed'),
354 ('>', 'unsigned')]:
355 if CHECK_CODE(conf,
356 f'static int test_array[1 - 2 * !((({v})-1) {op} 0)];',
357 define=f'{define_name}_{signed.upper()}',
358 quote=False,
359 headers=headers,
360 local_include=False,
361 msg=f"Checking if '{v}' is {signed}"):
362 return True
364 return False
366 @conf
367 def CHECK_VALUEOF(conf, v, headers=None, define=None, lib=None):
368 '''check the value of a variable/define'''
369 ret = True
370 v_define = define
371 if v_define is None:
372 v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_')
373 if CHECK_CODE(conf,
374 'printf("%%u", (unsigned)(%s))' % v,
375 define=v_define,
376 execute=True,
377 define_ret=True,
378 quote=False,
379 lib=lib,
380 headers=headers,
381 local_include=False,
382 msg="Checking value of %s" % v):
383 return int(conf.env[v_define])
385 return None
387 @conf
388 def CHECK_CODE(conf, code, define,
389 always=False, execute=False, addmain=True,
390 add_headers=True, mandatory=False,
391 headers=None, msg=None, cflags='', includes='# .',
392 local_include=True, lib=None, link=True,
393 define_ret=False, quote=False,
394 on_target=True, strict=False):
395 '''check if some code compiles and/or runs'''
397 if CONFIG_SET(conf, define):
398 return True
400 if headers is not None:
401 CHECK_HEADERS(conf, headers=headers, lib=lib)
403 if add_headers:
404 hdrs = header_list(conf, headers=headers, lib=lib)
405 else:
406 hdrs = ''
407 if execute:
408 execute = 1
409 else:
410 execute = 0
412 if addmain:
413 fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code)
414 else:
415 fragment='%s\n%s\n' % (hdrs, code)
417 if msg is None:
418 msg="Checking for %s" % define
420 cflags = TO_LIST(cflags)
422 # Be strict when relying on a compiler check
423 # Some compilers (e.g. xlc) ignore non-supported features as warnings
424 if strict:
425 if 'WERROR_CFLAGS' in conf.env:
426 cflags.extend(conf.env['WERROR_CFLAGS'])
428 if local_include:
429 cflags.append('-I%s' % conf.path.abspath())
431 if not link:
432 type='nolink'
433 else:
434 type='cprogram'
436 uselib = TO_LIST(lib)
438 (ccflags, ldflags, cpppath) = library_flags(conf, uselib)
440 includes = TO_LIST(includes)
441 includes.extend(cpppath)
443 uselib = [l.upper() for l in uselib]
445 cflags.extend(ccflags)
447 if on_target:
448 test_args = conf.SAMBA_CROSS_ARGS(msg=msg)
449 else:
450 test_args = []
452 conf.COMPOUND_START(msg)
454 try:
455 ret = conf.check(fragment=fragment,
456 execute=execute,
457 define_name = define,
458 cflags=cflags,
459 ldflags=ldflags,
460 includes=includes,
461 uselib=uselib,
462 type=type,
463 msg=msg,
464 quote=quote,
465 test_args=test_args,
466 define_ret=define_ret)
467 except Exception:
468 if always:
469 conf.DEFINE(define, 0)
470 else:
471 conf.undefine(define)
472 conf.COMPOUND_END(False)
473 if mandatory:
474 raise
475 return False
476 else:
477 # Success is indicated by ret but we should unset
478 # defines set by WAF's c_config.check() because it
479 # defines it to int(ret) and we want to undefine it
480 if not ret:
481 conf.undefine(define)
482 conf.COMPOUND_END(False)
483 return False
484 if not define_ret:
485 conf.DEFINE(define, 1)
486 conf.COMPOUND_END(True)
487 else:
488 conf.DEFINE(define, ret, quote=quote)
489 conf.COMPOUND_END(ret)
490 return True
493 @conf
494 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
495 always=False, define=None, headers=None,
496 lib=None):
497 '''check for a structure member'''
498 if define is None:
499 define = 'HAVE_%s' % member.upper()
500 return CHECK_CODE(conf,
501 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
502 define,
503 execute=False,
504 link=False,
505 lib=lib,
506 always=always,
507 headers=headers,
508 local_include=False,
509 msg="Checking for member %s in %s" % (member, structname))
512 @conf
513 def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n',
514 mandatory=False):
515 '''check if the given cflags are accepted by the compiler
517 check_cflags = TO_LIST(cflags)
518 if 'WERROR_CFLAGS' in conf.env:
519 check_cflags.extend(conf.env['WERROR_CFLAGS'])
520 return conf.check(fragment=fragment,
521 execute=0,
522 mandatory=mandatory,
523 type='nolink',
524 cflags=check_cflags,
525 msg="Checking compiler accepts %s" % cflags)
527 @conf
528 def CHECK_LDFLAGS(conf, ldflags,
529 mandatory=False):
530 '''check if the given ldflags are accepted by the linker
532 return conf.check(fragment='int main(void) { return 0; }\n',
533 execute=0,
534 ldflags=ldflags,
535 mandatory=mandatory,
536 msg="Checking linker accepts %s" % ldflags)
539 @conf
540 def CONFIG_GET(conf, option):
541 '''return True if a configuration option was found'''
542 if (option in conf.env):
543 return conf.env[option]
544 else:
545 return None
547 @conf
548 def CONFIG_SET(conf, option):
549 '''return True if a configuration option was found'''
550 if option not in conf.env:
551 return False
552 v = conf.env[option]
553 if v is None:
554 return False
555 if v == []:
556 return False
557 if v == ():
558 return False
559 return True
561 @conf
562 def CONFIG_RESET(conf, option):
563 if option not in conf.env:
564 return
565 del conf.env[option]
567 Build.BuildContext.CONFIG_RESET = CONFIG_RESET
568 Build.BuildContext.CONFIG_SET = CONFIG_SET
569 Build.BuildContext.CONFIG_GET = CONFIG_GET
572 def library_flags(self, libs):
573 '''work out flags from pkg_config'''
574 ccflags = []
575 ldflags = []
576 cpppath = []
577 for lib in TO_LIST(libs):
578 # note that we do not add the -I and -L in here, as that is added by the waf
579 # core. Adding it here would just change the order that it is put on the link line
580 # which can cause system paths to be added before internal libraries
581 extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
582 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
583 extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
584 ccflags.extend(extra_ccflags)
585 ldflags.extend(extra_ldflags)
586 cpppath.extend(extra_cpppath)
588 extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
589 cpppath.extend(extra_cpppath)
590 if 'EXTRA_LDFLAGS' in self.env:
591 ldflags.extend(self.env['EXTRA_LDFLAGS'])
593 ccflags = unique_list(ccflags)
594 ldflags = unique_list(ldflags)
595 cpppath = unique_list(cpppath)
596 return (ccflags, ldflags, cpppath)
599 @conf
600 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
601 '''check if a set of libraries exist as system libraries
603 returns the sublist of libs that do exist as a syslib or []
606 fragment= '''
607 int foo()
609 int v = 2;
610 return v*2;
613 ret = []
614 liblist = TO_LIST(libs)
615 for lib in liblist[:]:
616 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
617 ret.append(lib)
618 continue
620 (ccflags, ldflags, cpppath) = library_flags(conf, lib)
621 if shlib:
622 res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
623 else:
624 res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
626 if not res:
627 if mandatory:
628 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
629 sys.exit(1)
630 if empty_decl:
631 # if it isn't a mandatory library, then remove it from dependency lists
632 if set_target:
633 SET_TARGET_TYPE(conf, lib, 'EMPTY')
634 else:
635 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
636 conf.env['LIB_' + lib.upper()] = lib
637 if set_target:
638 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
639 ret.append(lib)
641 return ret
645 @conf
646 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
647 headers=None, link=True, empty_decl=True, set_target=True):
649 check that the functions in 'list' are available in 'library'
650 if they are, then make that library available as a dependency
652 if the library is not available and mandatory==True, then
653 raise an error.
655 If the library is not available and mandatory==False, then
656 add the library to the list of dependencies to remove from
657 build rules
659 optionally check for the functions first in libc
661 remaining = TO_LIST(list)
662 liblist = TO_LIST(library)
664 # check if some already found
665 for f in remaining[:]:
666 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
667 remaining.remove(f)
669 # see if the functions are in libc
670 if checklibc:
671 for f in remaining[:]:
672 if CHECK_FUNC(conf, f, link=True, headers=headers):
673 remaining.remove(f)
675 if remaining == []:
676 for lib in liblist:
677 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
678 SET_TARGET_TYPE(conf, lib, 'EMPTY')
679 return True
681 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
682 for lib in liblist[:]:
683 if not lib in checklist and mandatory:
684 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
685 sys.exit(1)
687 ret = True
688 for f in remaining:
689 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
690 ret = False
692 return ret
695 @conf
696 def IN_LAUNCH_DIR(conf):
697 '''return True if this rule is being run from the launch directory'''
698 return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
699 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
702 @conf
703 def SAMBA_CONFIG_H(conf, path=None):
704 '''write out config.h in the right directory'''
705 # we don't want to produce a config.h in places like lib/replace
706 # when we are building projects that depend on lib/replace
707 if not IN_LAUNCH_DIR(conf):
708 return
710 # we need to build real code that can't be optimized away to test
711 stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
712 for stack_protect_flag in stack_protect_list:
713 flag_supported = conf.check(fragment='''
714 #include <stdio.h>
716 int main(void)
718 char t[100000];
719 while (fgets(t, sizeof(t), stdin));
720 return 0;
722 ''',
723 execute=0,
724 cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
725 mandatory=False,
726 msg='Checking if compiler accepts %s' % (stack_protect_flag))
727 if flag_supported:
728 conf.ADD_CFLAGS('%s' % (stack_protect_flag))
729 break
731 flag_supported = conf.check(fragment='''
732 #include <stdio.h>
734 int main(void)
736 char t[100000];
737 while (fgets(t, sizeof(t), stdin));
738 return 0;
740 ''',
741 execute=0,
742 cflags=[ '-Werror', '-fstack-clash-protection'],
743 mandatory=False,
744 msg='Checking if compiler accepts -fstack-clash-protection')
745 if flag_supported:
746 conf.ADD_CFLAGS('-fstack-clash-protection')
748 if Options.options.debug:
749 conf.ADD_CFLAGS('-g', testflags=True)
751 if Options.options.pidl_developer:
752 conf.env.PIDL_DEVELOPER_MODE = True
754 if Options.options.developer:
755 conf.env.DEVELOPER_MODE = True
757 conf.ADD_CFLAGS('-g', testflags=True)
758 conf.ADD_CFLAGS('-Wall', testflags=True)
759 conf.ADD_CFLAGS('-Wshadow', testflags=True)
760 conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
761 if CHECK_CODE(conf,
762 'struct a { int b; }; struct c { struct a d; } e = { };',
763 'CHECK_C99_INIT',
764 link=False,
765 cflags='-Wmissing-field-initializers -Werror=missing-field-initializers',
766 msg="Checking C99 init of nested structs."):
767 conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True)
768 conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True)
769 conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True)
770 conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
771 conf.ADD_CFLAGS('-fno-common', testflags=True)
773 conf.ADD_CFLAGS('-Werror=address', testflags=True)
774 # we add these here to ensure that -Wstrict-prototypes is not set during configure
775 conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
776 testflags=True)
777 conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
778 testflags=True)
779 conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
780 testflags=True)
781 conf.ADD_CFLAGS('-Werror=implicit-int',
782 testflags=True)
783 conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
784 testflags=True)
785 conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
786 testflags=True)
787 conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
788 testflags=True)
789 conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
790 testflags=True)
791 conf.ADD_CFLAGS('-Wimplicit-fallthrough',
792 testflags=True)
793 conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
794 testflags=True)
795 conf.ADD_CFLAGS('-Werror=old-style-definition -Wold-style-definition',
796 testflags=True)
798 conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
799 conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
800 conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
801 testflags=True, prereq_flags='-Wformat')
802 # This check is because for ldb_search(), a NULL format string
803 # is not an error, but some compilers complain about that.
804 if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
805 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
807 int main(void) {
808 testformat(0);
809 return 0;
812 '''):
813 if not 'EXTRA_CFLAGS' in conf.env:
814 conf.env['EXTRA_CFLAGS'] = []
815 conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
817 if CHECK_CFLAGS(conf, ["-Wno-error=array-bounds"]):
818 conf.define('HAVE_WNO_ERROR_ARRAY_BOUNDS', 1)
820 if not Options.options.disable_warnings_as_errors:
821 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
822 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
823 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=cast-align', testflags=True)
825 if Options.options.fatal_errors:
826 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
828 if Options.options.pedantic:
829 conf.ADD_CFLAGS('-W', testflags=True)
831 if (Options.options.address_sanitizer or
832 Options.options.undefined_sanitizer):
833 conf.ADD_CFLAGS('-g -O1', testflags=True)
834 if (Options.options.address_sanitizer
835 or Options.options.memory_sanitizer):
836 conf.ADD_CFLAGS('-fno-omit-frame-pointer', testflags=True)
837 if Options.options.address_sanitizer:
838 conf.ADD_CFLAGS('-fsanitize=address', testflags=True)
839 conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
840 conf.env['ADDRESS_SANITIZER'] = True
841 if Options.options.undefined_sanitizer:
842 conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True)
843 conf.ADD_CFLAGS('-fsanitize=null', testflags=True)
844 conf.ADD_CFLAGS('-fsanitize=alignment', testflags=True)
845 conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True)
846 conf.env['UNDEFINED_SANITIZER'] = True
848 # MemorySanitizer is only available if you build with clang
849 if Options.options.memory_sanitizer:
850 conf.ADD_CFLAGS('-g -O2', testflags=True)
851 conf.ADD_CFLAGS('-fsanitize=memory', testflags=True)
852 conf.ADD_CFLAGS('-fsanitize-memory-track-origins=2', testflags=True)
853 conf.ADD_LDFLAGS('-fsanitize=memory')
854 conf.env['MEMORY_SANITIZER'] = True
856 # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
857 # environment variables which are only used the for final build.
859 # The CFLAGS and LDFLAGS environment variables are also
860 # used for the configure checks which might impact their results.
862 # If these variables don't pass a smoke test, fail the configure
864 conf.add_os_flags('ADDITIONAL_CFLAGS')
865 if conf.env.ADDITIONAL_CFLAGS:
866 conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS'],
867 mandatory=True)
868 conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
870 conf.add_os_flags('ADDITIONAL_LDFLAGS')
871 if conf.env.ADDITIONAL_LDFLAGS:
872 conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS'],
873 mandatory=True)
874 conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
876 if path is None:
877 conf.write_config_header('default/config.h', top=True, remove=False)
878 else:
879 conf.write_config_header(os.path.join(conf.variant, path), remove=False)
880 for key in conf.env.define_key:
881 conf.undefine(key, from_env=False)
882 conf.env.define_key = []
883 conf.SAMBA_CROSS_CHECK_COMPLETE()
886 @conf
887 def CONFIG_PATH(conf, name, default):
888 '''setup a configurable path'''
889 if not name in conf.env:
890 if default[0] == '/':
891 conf.env[name] = default
892 else:
893 conf.env[name] = conf.env['PREFIX'] + default
895 @conf
896 def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=None):
897 '''add some CFLAGS to the command line
898 optionally set testflags to ensure all the flags work
900 if prereq_flags is None:
901 prereq_flags = []
902 prereq_flags = TO_LIST(prereq_flags)
903 if testflags:
904 ok_flags=[]
905 for f in flags.split():
906 if CHECK_CFLAGS(conf, [f] + prereq_flags):
907 ok_flags.append(f)
908 flags = ok_flags
909 if not name in conf.env:
910 conf.env[name] = []
911 conf.env[name].extend(TO_LIST(flags))
913 @conf
914 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=None):
915 '''add some CFLAGS to the command line
916 optionally set testflags to ensure all the flags work
918 if prereq_flags is None:
919 prereq_flags = []
920 ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
921 prereq_flags=prereq_flags)
923 @conf
924 def ADD_LDFLAGS(conf, flags, testflags=False):
925 '''add some LDFLAGS to the command line
926 optionally set testflags to ensure all the flags work
928 this will return the flags that are added, if any
930 if testflags:
931 ok_flags=[]
932 for f in flags.split():
933 if CHECK_LDFLAGS(conf, f):
934 ok_flags.append(f)
935 flags = ok_flags
936 if not 'EXTRA_LDFLAGS' in conf.env:
937 conf.env['EXTRA_LDFLAGS'] = []
938 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
939 return flags
942 @conf
943 def ADD_EXTRA_INCLUDES(conf, includes):
944 '''add some extra include directories to all builds'''
945 if not 'EXTRA_INCLUDES' in conf.env:
946 conf.env['EXTRA_INCLUDES'] = []
947 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
951 def CURRENT_CFLAGS(bld, target, cflags,
952 allow_warnings=False,
953 use_hostcc=False,
954 hide_symbols=False):
955 '''work out the current flags. local flags are added first'''
956 ret = []
957 if use_hostcc:
958 ret += ['-D_SAMBA_HOSTCC_']
959 ret += TO_LIST(cflags)
960 if not 'EXTRA_CFLAGS' in bld.env:
961 list = []
962 else:
963 list = bld.env['EXTRA_CFLAGS'];
964 ret.extend(list)
965 if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
966 list = bld.env['PICKY_CFLAGS'];
967 ret.extend(list)
968 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
969 ret.append(bld.env.VISIBILITY_CFLAGS)
970 return ret
973 @conf
974 def CHECK_CC_ENV(conf):
975 """trim whitespaces from 'CC'.
976 The build farm sometimes puts a space at the start"""
977 if os.environ.get('CC'):
978 conf.env.CC = TO_LIST(os.environ.get('CC'))
981 @conf
982 def SETUP_CONFIGURE_CACHE(conf, enable):
983 '''enable/disable cache of configure results'''
984 if enable:
985 # when -C is chosen, we will use a private cache and will
986 # not look into system includes. This roughly matches what
987 # autoconf does with -C
988 cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
989 mkdir_p(cache_path)
990 Options.cache_global = os.environ['WAFCACHE'] = cache_path
991 else:
992 # when -C is not chosen we will not cache configure checks
993 # We set the recursion limit low to prevent waf from spending
994 # a lot of time on the signatures of the files.
995 Options.cache_global = os.environ['WAFCACHE'] = ''
996 preproc.recursion_limit = 1
997 # in either case we don't need to scan system includes
998 preproc.go_absolute = False
1001 @conf
1002 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
1003 if (Options.options.address_sanitizer
1004 or Options.options.memory_sanitizer
1005 or Options.options.enable_libfuzzer):
1006 # Sanitizers can rely on symbols undefined at library link time and the
1007 # symbols used for fuzzers are only defined by compiler wrappers.
1008 return
1010 if not sys.platform.startswith("openbsd"):
1011 # we don't want any libraries or modules to rely on runtime
1012 # resolution of symbols
1013 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
1015 if (conf.env.undefined_ignore_ldflags == [] and
1016 conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'])):
1017 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']