wafsamba: allow cflags for CHECK_TYPE[_IN]()
[Samba.git] / buildtools / wafsamba / samba_autoconf.py
blob3ca2f33419010a737440861ce0a1de2a1396ec87
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 '''check for a variable declaration (or define)'''
190 if define is None:
191 define = 'HAVE_%s' % v.upper()
193 if msg is None:
194 msg="Checking for variable %s" % v
196 return CHECK_CODE(conf,
197 # we need to make sure the compiler doesn't
198 # optimize it out...
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)
215 @conf
216 def CHECK_DECLS(conf, vars, reverse=False, headers=None, lib=None, always=False):
217 '''check a list of variable declarations, using the HAVE_DECL_xxx form
218 of define
220 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
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 lib=lib,
232 msg='Checking for declaration of %s' % v,
233 always=always):
234 if not CHECK_CODE(conf,
236 return (int)%s;
237 ''' % (v),
238 execute=False,
239 link=False,
240 msg='Checking for declaration of %s (as enum)' % v,
241 local_include=False,
242 headers=headers,
243 lib=lib,
244 define=define,
245 always=always):
246 ret = False
247 return ret
250 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
251 '''check for a function'''
252 define='HAVE_%s' % f.upper()
254 ret = False
256 in_lib_str = ""
257 if lib:
258 in_lib_str = " in %s" % lib
259 conf.COMPOUND_START('Checking for %s%s' % (f, in_lib_str))
261 if link is None or link:
262 ret = CHECK_CODE(conf,
263 # this is based on the autoconf strategy
265 #define %s __fake__%s
266 #ifdef HAVE_LIMITS_H
267 # include <limits.h>
268 #else
269 # include <assert.h>
270 #endif
271 #undef %s
272 #if defined __stub_%s || defined __stub___%s
273 #error "bad glibc stub"
274 #endif
275 extern char %s();
276 int main() { return %s(); }
277 ''' % (f, f, f, f, f, f, f),
278 execute=False,
279 link=True,
280 addmain=False,
281 add_headers=False,
282 define=define,
283 local_include=False,
284 lib=lib,
285 headers=headers,
286 msg='Checking for %s' % f)
288 if not ret:
289 ret = CHECK_CODE(conf,
290 # it might be a macro
291 # we need to make sure the compiler doesn't
292 # optimize it out...
293 'void *__x = (void *)%s; return (int)__x' % f,
294 execute=False,
295 link=True,
296 addmain=True,
297 add_headers=True,
298 define=define,
299 local_include=False,
300 lib=lib,
301 headers=headers,
302 msg='Checking for macro %s' % f)
304 if not ret and (link is None or not link):
305 ret = CHECK_VARIABLE(conf, f,
306 define=define,
307 headers=headers,
308 msg='Checking for declaration of %s' % f)
309 conf.COMPOUND_END(ret)
310 return ret
313 @conf
314 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
315 '''check for a list of functions'''
316 ret = True
317 for f in TO_LIST(list):
318 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
319 ret = False
320 return ret
323 @conf
324 def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True):
325 '''check the size of a type'''
326 for v in TO_LIST(vars):
327 v_define = define
328 ret = False
329 if v_define is None:
330 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
331 for size in list((1, 2, 4, 8, 16, 32, 64)):
332 if CHECK_CODE(conf,
333 'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size),
334 define=v_define,
335 quote=False,
336 headers=headers,
337 local_include=False,
338 msg="Checking if size of %s == %d" % (v, size)):
339 conf.DEFINE(v_define, size)
340 ret = True
341 break
342 if not ret and critical:
343 Logs.error("Couldn't determine size of '%s'" % v)
344 sys.exit(1)
345 return ret
347 @conf
348 def CHECK_SIGN(conf, v, headers=None):
349 '''check the sign of a type'''
350 define_name = v.upper().replace(' ', '_')
351 for op, signed in [('<', 'signed'),
352 ('>', 'unsigned')]:
353 if CHECK_CODE(conf,
354 f'static int test_array[1 - 2 * !((({v})-1) {op} 0)];',
355 define=f'{define_name}_{signed.upper()}',
356 quote=False,
357 headers=headers,
358 local_include=False,
359 msg=f"Checking if '{v}' is {signed}"):
360 return True
362 return False
364 @conf
365 def CHECK_VALUEOF(conf, v, headers=None, define=None):
366 '''check the value of a variable/define'''
367 ret = True
368 v_define = define
369 if v_define is None:
370 v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_')
371 if CHECK_CODE(conf,
372 'printf("%%u", (unsigned)(%s))' % v,
373 define=v_define,
374 execute=True,
375 define_ret=True,
376 quote=False,
377 headers=headers,
378 local_include=False,
379 msg="Checking value of %s" % v):
380 return int(conf.env[v_define])
382 return None
384 @conf
385 def CHECK_CODE(conf, code, define,
386 always=False, execute=False, addmain=True,
387 add_headers=True, mandatory=False,
388 headers=None, msg=None, cflags='', includes='# .',
389 local_include=True, lib=None, link=True,
390 define_ret=False, quote=False,
391 on_target=True, strict=False):
392 '''check if some code compiles and/or runs'''
394 if CONFIG_SET(conf, define):
395 return True
397 if headers is not None:
398 CHECK_HEADERS(conf, headers=headers, lib=lib)
400 if add_headers:
401 hdrs = header_list(conf, headers=headers, lib=lib)
402 else:
403 hdrs = ''
404 if execute:
405 execute = 1
406 else:
407 execute = 0
409 if addmain:
410 fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code)
411 else:
412 fragment='%s\n%s\n' % (hdrs, code)
414 if msg is None:
415 msg="Checking for %s" % define
417 cflags = TO_LIST(cflags)
419 # Be strict when relying on a compiler check
420 # Some compilers (e.g. xlc) ignore non-supported features as warnings
421 if strict:
422 if 'WERROR_CFLAGS' in conf.env:
423 cflags.extend(conf.env['WERROR_CFLAGS'])
425 if local_include:
426 cflags.append('-I%s' % conf.path.abspath())
428 if not link:
429 type='nolink'
430 else:
431 type='cprogram'
433 uselib = TO_LIST(lib)
435 (ccflags, ldflags, cpppath) = library_flags(conf, uselib)
437 includes = TO_LIST(includes)
438 includes.extend(cpppath)
440 uselib = [l.upper() for l in uselib]
442 cflags.extend(ccflags)
444 if on_target:
445 test_args = conf.SAMBA_CROSS_ARGS(msg=msg)
446 else:
447 test_args = []
449 conf.COMPOUND_START(msg)
451 try:
452 ret = conf.check(fragment=fragment,
453 execute=execute,
454 define_name = define,
455 cflags=cflags,
456 ldflags=ldflags,
457 includes=includes,
458 uselib=uselib,
459 type=type,
460 msg=msg,
461 quote=quote,
462 test_args=test_args,
463 define_ret=define_ret)
464 except Exception:
465 if always:
466 conf.DEFINE(define, 0)
467 else:
468 conf.undefine(define)
469 conf.COMPOUND_END(False)
470 if mandatory:
471 raise
472 return False
473 else:
474 # Success is indicated by ret but we should unset
475 # defines set by WAF's c_config.check() because it
476 # defines it to int(ret) and we want to undefine it
477 if not ret:
478 conf.undefine(define)
479 conf.COMPOUND_END(False)
480 return False
481 if not define_ret:
482 conf.DEFINE(define, 1)
483 conf.COMPOUND_END(True)
484 else:
485 conf.DEFINE(define, ret, quote=quote)
486 conf.COMPOUND_END(ret)
487 return True
490 @conf
491 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
492 always=False, define=None, headers=None,
493 lib=None):
494 '''check for a structure member'''
495 if define is None:
496 define = 'HAVE_%s' % member.upper()
497 return CHECK_CODE(conf,
498 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
499 define,
500 execute=False,
501 link=False,
502 lib=lib,
503 always=always,
504 headers=headers,
505 local_include=False,
506 msg="Checking for member %s in %s" % (member, structname))
509 @conf
510 def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n',
511 mandatory=False):
512 '''check if the given cflags are accepted by the compiler
514 check_cflags = TO_LIST(cflags)
515 if 'WERROR_CFLAGS' in conf.env:
516 check_cflags.extend(conf.env['WERROR_CFLAGS'])
517 return conf.check(fragment=fragment,
518 execute=0,
519 mandatory=mandatory,
520 type='nolink',
521 cflags=check_cflags,
522 msg="Checking compiler accepts %s" % cflags)
524 @conf
525 def CHECK_LDFLAGS(conf, ldflags,
526 mandatory=False):
527 '''check if the given ldflags are accepted by the linker
529 return conf.check(fragment='int main(void) { return 0; }\n',
530 execute=0,
531 ldflags=ldflags,
532 mandatory=mandatory,
533 msg="Checking linker accepts %s" % ldflags)
536 @conf
537 def CONFIG_GET(conf, option):
538 '''return True if a configuration option was found'''
539 if (option in conf.env):
540 return conf.env[option]
541 else:
542 return None
544 @conf
545 def CONFIG_SET(conf, option):
546 '''return True if a configuration option was found'''
547 if option not in conf.env:
548 return False
549 v = conf.env[option]
550 if v is None:
551 return False
552 if v == []:
553 return False
554 if v == ():
555 return False
556 return True
558 @conf
559 def CONFIG_RESET(conf, option):
560 if option not in conf.env:
561 return
562 del conf.env[option]
564 Build.BuildContext.CONFIG_RESET = CONFIG_RESET
565 Build.BuildContext.CONFIG_SET = CONFIG_SET
566 Build.BuildContext.CONFIG_GET = CONFIG_GET
569 def library_flags(self, libs):
570 '''work out flags from pkg_config'''
571 ccflags = []
572 ldflags = []
573 cpppath = []
574 for lib in TO_LIST(libs):
575 # note that we do not add the -I and -L in here, as that is added by the waf
576 # core. Adding it here would just change the order that it is put on the link line
577 # which can cause system paths to be added before internal libraries
578 extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
579 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
580 extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
581 ccflags.extend(extra_ccflags)
582 ldflags.extend(extra_ldflags)
583 cpppath.extend(extra_cpppath)
585 extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
586 cpppath.extend(extra_cpppath)
587 if 'EXTRA_LDFLAGS' in self.env:
588 ldflags.extend(self.env['EXTRA_LDFLAGS'])
590 ccflags = unique_list(ccflags)
591 ldflags = unique_list(ldflags)
592 cpppath = unique_list(cpppath)
593 return (ccflags, ldflags, cpppath)
596 @conf
597 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
598 '''check if a set of libraries exist as system libraries
600 returns the sublist of libs that do exist as a syslib or []
603 fragment= '''
604 int foo()
606 int v = 2;
607 return v*2;
610 ret = []
611 liblist = TO_LIST(libs)
612 for lib in liblist[:]:
613 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
614 ret.append(lib)
615 continue
617 (ccflags, ldflags, cpppath) = library_flags(conf, lib)
618 if shlib:
619 res = conf.check(features='c cshlib', fragment=fragment, lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
620 else:
621 res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
623 if not res:
624 if mandatory:
625 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
626 sys.exit(1)
627 if empty_decl:
628 # if it isn't a mandatory library, then remove it from dependency lists
629 if set_target:
630 SET_TARGET_TYPE(conf, lib, 'EMPTY')
631 else:
632 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
633 conf.env['LIB_' + lib.upper()] = lib
634 if set_target:
635 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
636 ret.append(lib)
638 return ret
642 @conf
643 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
644 headers=None, link=True, empty_decl=True, set_target=True):
646 check that the functions in 'list' are available in 'library'
647 if they are, then make that library available as a dependency
649 if the library is not available and mandatory==True, then
650 raise an error.
652 If the library is not available and mandatory==False, then
653 add the library to the list of dependencies to remove from
654 build rules
656 optionally check for the functions first in libc
658 remaining = TO_LIST(list)
659 liblist = TO_LIST(library)
661 # check if some already found
662 for f in remaining[:]:
663 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
664 remaining.remove(f)
666 # see if the functions are in libc
667 if checklibc:
668 for f in remaining[:]:
669 if CHECK_FUNC(conf, f, link=True, headers=headers):
670 remaining.remove(f)
672 if remaining == []:
673 for lib in liblist:
674 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
675 SET_TARGET_TYPE(conf, lib, 'EMPTY')
676 return True
678 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
679 for lib in liblist[:]:
680 if not lib in checklist and mandatory:
681 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
682 sys.exit(1)
684 ret = True
685 for f in remaining:
686 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
687 ret = False
689 return ret
692 @conf
693 def IN_LAUNCH_DIR(conf):
694 '''return True if this rule is being run from the launch directory'''
695 return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
696 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
699 @conf
700 def SAMBA_CONFIG_H(conf, path=None):
701 '''write out config.h in the right directory'''
702 # we don't want to produce a config.h in places like lib/replace
703 # when we are building projects that depend on lib/replace
704 if not IN_LAUNCH_DIR(conf):
705 return
707 # we need to build real code that can't be optimized away to test
708 stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
709 for stack_protect_flag in stack_protect_list:
710 flag_supported = conf.check(fragment='''
711 #include <stdio.h>
713 int main(void)
715 char t[100000];
716 while (fgets(t, sizeof(t), stdin));
717 return 0;
719 ''',
720 execute=0,
721 cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
722 mandatory=False,
723 msg='Checking if compiler accepts %s' % (stack_protect_flag))
724 if flag_supported:
725 conf.ADD_CFLAGS('%s' % (stack_protect_flag))
726 break
728 flag_supported = conf.check(fragment='''
729 #include <stdio.h>
731 int main(void)
733 char t[100000];
734 while (fgets(t, sizeof(t), stdin));
735 return 0;
737 ''',
738 execute=0,
739 cflags=[ '-Werror', '-fstack-clash-protection'],
740 mandatory=False,
741 msg='Checking if compiler accepts -fstack-clash-protection')
742 if flag_supported:
743 conf.ADD_CFLAGS('-fstack-clash-protection')
745 if Options.options.debug:
746 conf.ADD_CFLAGS('-g', testflags=True)
748 if Options.options.pidl_developer:
749 conf.env.PIDL_DEVELOPER_MODE = True
751 if Options.options.developer:
752 conf.env.DEVELOPER_MODE = True
754 conf.ADD_CFLAGS('-g', testflags=True)
755 conf.ADD_CFLAGS('-Wall', testflags=True)
756 conf.ADD_CFLAGS('-Wshadow', testflags=True)
757 conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
758 if CHECK_CODE(conf,
759 'struct a { int b; }; struct c { struct a d; } e = { };',
760 'CHECK_C99_INIT',
761 link=False,
762 cflags='-Wmissing-field-initializers -Werror=missing-field-initializers',
763 msg="Checking C99 init of nested structs."):
764 conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True)
765 conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True)
766 conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True)
767 conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
768 conf.ADD_CFLAGS('-fno-common', testflags=True)
770 conf.ADD_CFLAGS('-Werror=address', testflags=True)
771 # we add these here to ensure that -Wstrict-prototypes is not set during configure
772 conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
773 testflags=True)
774 conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
775 testflags=True)
776 conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
777 testflags=True)
778 conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
779 testflags=True)
780 conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
781 testflags=True)
782 conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
783 testflags=True)
784 conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
785 testflags=True)
786 conf.ADD_CFLAGS('-Wimplicit-fallthrough',
787 testflags=True)
788 conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
789 testflags=True)
791 conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
792 conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
793 conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
794 testflags=True, prereq_flags='-Wformat')
795 # This check is because for ldb_search(), a NULL format string
796 # is not an error, but some compilers complain about that.
797 if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
798 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
800 int main(void) {
801 testformat(0);
802 return 0;
805 '''):
806 if not 'EXTRA_CFLAGS' in conf.env:
807 conf.env['EXTRA_CFLAGS'] = []
808 conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
810 if CHECK_CFLAGS(conf, ["-Wno-error=array-bounds"]):
811 conf.define('HAVE_WNO_ERROR_ARRAY_BOUNDS', 1)
813 if not Options.options.disable_warnings_as_errors:
814 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
815 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
816 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=cast-align', testflags=True)
818 if Options.options.fatal_errors:
819 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
821 if Options.options.pedantic:
822 conf.ADD_CFLAGS('-W', testflags=True)
824 if (Options.options.address_sanitizer or
825 Options.options.undefined_sanitizer):
826 conf.ADD_CFLAGS('-g -O1', testflags=True)
827 if Options.options.address_sanitizer:
828 conf.ADD_CFLAGS('-fno-omit-frame-pointer', testflags=True)
829 conf.ADD_CFLAGS('-fsanitize=address', testflags=True)
830 conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
831 conf.env['ADDRESS_SANITIZER'] = True
832 if Options.options.undefined_sanitizer:
833 conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True)
834 conf.ADD_CFLAGS('-fsanitize=null', testflags=True)
835 conf.ADD_CFLAGS('-fsanitize=alignment', testflags=True)
836 conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True)
837 conf.env['UNDEFINED_SANITIZER'] = True
840 # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
841 # environment variables which are only used the for final build.
843 # The CFLAGS and LDFLAGS environment variables are also
844 # used for the configure checks which might impact their results.
846 # If these variables don't pass a smoke test, fail the configure
848 conf.add_os_flags('ADDITIONAL_CFLAGS')
849 if conf.env.ADDITIONAL_CFLAGS:
850 conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS'],
851 mandatory=True)
852 conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
854 conf.add_os_flags('ADDITIONAL_LDFLAGS')
855 if conf.env.ADDITIONAL_LDFLAGS:
856 conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS'],
857 mandatory=True)
858 conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
860 if path is None:
861 conf.write_config_header('default/config.h', top=True, remove=False)
862 else:
863 conf.write_config_header(os.path.join(conf.variant, path), remove=False)
864 for key in conf.env.define_key:
865 conf.undefine(key, from_env=False)
866 conf.env.define_key = []
867 conf.SAMBA_CROSS_CHECK_COMPLETE()
870 @conf
871 def CONFIG_PATH(conf, name, default):
872 '''setup a configurable path'''
873 if not name in conf.env:
874 if default[0] == '/':
875 conf.env[name] = default
876 else:
877 conf.env[name] = conf.env['PREFIX'] + default
879 @conf
880 def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]):
881 '''add some CFLAGS to the command line
882 optionally set testflags to ensure all the flags work
884 prereq_flags = TO_LIST(prereq_flags)
885 if testflags:
886 ok_flags=[]
887 for f in flags.split():
888 if CHECK_CFLAGS(conf, [f] + prereq_flags):
889 ok_flags.append(f)
890 flags = ok_flags
891 if not name in conf.env:
892 conf.env[name] = []
893 conf.env[name].extend(TO_LIST(flags))
895 @conf
896 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]):
897 '''add some CFLAGS to the command line
898 optionally set testflags to ensure all the flags work
900 ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
901 prereq_flags=prereq_flags)
903 @conf
904 def ADD_LDFLAGS(conf, flags, testflags=False):
905 '''add some LDFLAGS to the command line
906 optionally set testflags to ensure all the flags work
908 this will return the flags that are added, if any
910 if testflags:
911 ok_flags=[]
912 for f in flags.split():
913 if CHECK_LDFLAGS(conf, f):
914 ok_flags.append(f)
915 flags = ok_flags
916 if not 'EXTRA_LDFLAGS' in conf.env:
917 conf.env['EXTRA_LDFLAGS'] = []
918 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
919 return flags
922 @conf
923 def ADD_EXTRA_INCLUDES(conf, includes):
924 '''add some extra include directories to all builds'''
925 if not 'EXTRA_INCLUDES' in conf.env:
926 conf.env['EXTRA_INCLUDES'] = []
927 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
931 def CURRENT_CFLAGS(bld, target, cflags,
932 allow_warnings=False,
933 use_hostcc=False,
934 hide_symbols=False):
935 '''work out the current flags. local flags are added first'''
936 ret = []
937 if use_hostcc:
938 ret += ['-D_SAMBA_HOSTCC_']
939 ret += TO_LIST(cflags)
940 if not 'EXTRA_CFLAGS' in bld.env:
941 list = []
942 else:
943 list = bld.env['EXTRA_CFLAGS'];
944 ret.extend(list)
945 if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
946 list = bld.env['PICKY_CFLAGS'];
947 ret.extend(list)
948 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
949 ret.append(bld.env.VISIBILITY_CFLAGS)
950 return ret
953 @conf
954 def CHECK_CC_ENV(conf):
955 """trim whitespaces from 'CC'.
956 The build farm sometimes puts a space at the start"""
957 if os.environ.get('CC'):
958 conf.env.CC = TO_LIST(os.environ.get('CC'))
961 @conf
962 def SETUP_CONFIGURE_CACHE(conf, enable):
963 '''enable/disable cache of configure results'''
964 if enable:
965 # when -C is chosen, we will use a private cache and will
966 # not look into system includes. This roughtly matches what
967 # autoconf does with -C
968 cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
969 mkdir_p(cache_path)
970 Options.cache_global = os.environ['WAFCACHE'] = cache_path
971 else:
972 # when -C is not chosen we will not cache configure checks
973 # We set the recursion limit low to prevent waf from spending
974 # a lot of time on the signatures of the files.
975 Options.cache_global = os.environ['WAFCACHE'] = ''
976 preproc.recursion_limit = 1
977 # in either case we don't need to scan system includes
978 preproc.go_absolute = False
981 @conf
982 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
983 if Options.options.address_sanitizer or Options.options.enable_libfuzzer:
984 # Sanitizers can rely on symbols undefined at library link time and the
985 # symbols used for fuzzers are only defined by compiler wrappers.
986 return
988 if not sys.platform.startswith("openbsd"):
989 # we don't want any libraries or modules to rely on runtime
990 # resolution of symbols
991 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
993 if (conf.env.undefined_ignore_ldflags == [] and
994 conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'])):
995 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']