s3:printing: Allow to run samba-bgqd as a standalone systemd service
[Samba.git] / buildtools / wafsamba / samba_autoconf.py
blob802cbaced521dd4b2aea2d38762867611cb9898e
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, libs) = 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, libs) = 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, library):
573 '''work out flags from pkg_config'''
574 ccflags = []
575 ldflags = []
576 cpppath = []
577 libs = []
578 for lib in TO_LIST(library):
579 # note that we do not add the -I and -L in here, as that is added by the waf
580 # core. Adding it here would just change the order that it is put on the link line
581 # which can cause system paths to be added before internal libraries
582 extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), []))
583 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
584 extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
585 extra_libs = TO_LIST(getattr(self.env, 'LIB_%s' % lib.upper(), []))
586 ccflags.extend(extra_ccflags)
587 ldflags.extend(extra_ldflags)
588 cpppath.extend(extra_cpppath)
589 libs.extend(extra_libs)
591 extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), []))
592 cpppath.extend(extra_cpppath)
593 if 'EXTRA_LDFLAGS' in self.env:
594 ldflags.extend(self.env['EXTRA_LDFLAGS'])
596 ccflags = unique_list(ccflags)
597 ldflags = unique_list(ldflags)
598 cpppath = unique_list(cpppath)
599 libs = unique_list(libs)
600 return (ccflags, ldflags, cpppath, libs)
603 @conf
604 def CHECK_LIB(conf, library, mandatory=False, empty_decl=True, set_target=True, shlib=False):
605 '''check if a set of libraries exist as system libraries
607 returns the sublist of libs that do exist as a syslib or []
610 fragment= '''
611 int foo()
613 int v = 2;
614 return v*2;
617 ret = []
618 liblist = TO_LIST(library)
619 for lib in liblist:
620 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
621 ret.append(lib)
622 continue
624 (ccflags, ldflags, cpppath, libs) = library_flags(conf, lib)
625 if shlib:
626 # Avoid repeating the library if it is already named by
627 # pkg-config --libs.
628 kw = {}
629 if lib not in libs:
630 kw['lib'] = lib
631 res = conf.check(features='c cshlib', fragment=fragment, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False, **kw)
632 else:
633 res = conf.check(lib=lib, uselib_store=lib, cflags=ccflags, ldflags=ldflags, uselib=lib.upper(), mandatory=False)
635 if not res:
636 if mandatory:
637 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, libs))
638 sys.exit(1)
639 if empty_decl:
640 # if it isn't a mandatory library, then remove it from dependency lists
641 if set_target:
642 SET_TARGET_TYPE(conf, lib, 'EMPTY')
643 else:
644 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1)
645 # To avoid losing information from pkg-config, append the library
646 # only it is not already present.
647 if lib not in libs:
648 conf.env.append_value('LIB_' + lib.upper(), lib)
649 if set_target:
650 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
651 ret.append(lib)
653 return ret
657 @conf
658 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
659 headers=None, link=True, empty_decl=True, set_target=True):
661 check that the functions in 'list' are available in 'library'
662 if they are, then make that library available as a dependency
664 if the library is not available and mandatory==True, then
665 raise an error.
667 If the library is not available and mandatory==False, then
668 add the library to the list of dependencies to remove from
669 build rules
671 optionally check for the functions first in libc
673 remaining = TO_LIST(list)
674 liblist = TO_LIST(library)
676 # check if some already found
677 for f in remaining[:]:
678 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
679 remaining.remove(f)
681 # see if the functions are in libc
682 if checklibc:
683 for f in remaining[:]:
684 if CHECK_FUNC(conf, f, link=True, headers=headers):
685 remaining.remove(f)
687 if remaining == []:
688 for lib in liblist:
689 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
690 SET_TARGET_TYPE(conf, lib, 'EMPTY')
691 return True
693 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
694 for lib in liblist[:]:
695 if not lib in checklist and mandatory:
696 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
697 sys.exit(1)
699 ret = True
700 for f in remaining:
701 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
702 ret = False
704 return ret
707 @conf
708 def IN_LAUNCH_DIR(conf):
709 '''return True if this rule is being run from the launch directory'''
710 return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir)
711 Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR
714 @conf
715 def SAMBA_CONFIG_H(conf, path=None):
716 '''write out config.h in the right directory'''
717 # we don't want to produce a config.h in places like lib/replace
718 # when we are building projects that depend on lib/replace
719 if not IN_LAUNCH_DIR(conf):
720 return
722 # we need to build real code that can't be optimized away to test
723 stack_protect_list = ['-fstack-protector-strong', '-fstack-protector']
724 for stack_protect_flag in stack_protect_list:
725 flag_supported = conf.check(fragment='''
726 #include <stdio.h>
728 int main(void)
730 char t[100000];
731 while (fgets(t, sizeof(t), stdin));
732 return 0;
734 ''',
735 execute=0,
736 cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag],
737 mandatory=False,
738 msg='Checking if compiler accepts %s' % (stack_protect_flag))
739 if flag_supported:
740 conf.ADD_CFLAGS('%s' % (stack_protect_flag))
741 break
743 flag_supported = conf.check(fragment='''
744 #include <stdio.h>
746 int main(void)
748 char t[100000];
749 while (fgets(t, sizeof(t), stdin));
750 return 0;
752 ''',
753 execute=0,
754 cflags=[ '-Werror', '-fstack-clash-protection'],
755 mandatory=False,
756 msg='Checking if compiler accepts -fstack-clash-protection')
757 if flag_supported:
758 conf.ADD_CFLAGS('-fstack-clash-protection')
760 if Options.options.debug:
761 conf.ADD_CFLAGS('-g', testflags=True)
763 if Options.options.pidl_developer:
764 conf.env.PIDL_DEVELOPER_MODE = True
766 if Options.options.developer:
767 conf.env.DEVELOPER_MODE = True
769 conf.ADD_CFLAGS('-g', testflags=True)
770 conf.ADD_CFLAGS('-Wall', testflags=True)
771 conf.ADD_CFLAGS('-Wshadow', testflags=True)
772 conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True)
773 if CHECK_CODE(conf,
774 'struct a { int b; }; struct c { struct a d; } e = { };',
775 'CHECK_C99_INIT',
776 link=False,
777 cflags='-Wmissing-field-initializers -Werror=missing-field-initializers',
778 msg="Checking C99 init of nested structs."):
779 conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True)
780 conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True)
781 conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True)
782 conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True)
783 conf.ADD_CFLAGS('-fno-common', testflags=True)
785 conf.ADD_CFLAGS('-Werror=address', testflags=True)
786 # we add these here to ensure that -Wstrict-prototypes is not set during configure
787 conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes',
788 testflags=True)
789 conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings',
790 testflags=True)
791 conf.ADD_CFLAGS('-Werror-implicit-function-declaration',
792 testflags=True)
793 conf.ADD_CFLAGS('-Werror=implicit-int',
794 testflags=True)
795 conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith',
796 testflags=True)
797 conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement',
798 testflags=True)
799 conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type',
800 testflags=True)
801 conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized',
802 testflags=True)
803 conf.ADD_CFLAGS('-Wimplicit-fallthrough',
804 testflags=True)
805 conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2',
806 testflags=True)
807 conf.ADD_CFLAGS('-Werror=old-style-definition -Wold-style-definition',
808 testflags=True)
810 conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
811 conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
812 conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
813 testflags=True, prereq_flags='-Wformat')
814 # This check is because for ldb_search(), a NULL format string
815 # is not an error, but some compilers complain about that.
816 if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
817 int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
819 int main(void) {
820 testformat(0);
821 return 0;
824 '''):
825 if not 'EXTRA_CFLAGS' in conf.env:
826 conf.env['EXTRA_CFLAGS'] = []
827 conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format"))
829 if CHECK_CFLAGS(conf, ["-Wno-error=array-bounds"]):
830 conf.define('HAVE_WNO_ERROR_ARRAY_BOUNDS', 1)
832 if CHECK_CFLAGS(conf, ["-Wno-error=stringop-overflow"]):
833 conf.define('HAVE_WNO_ERROR_STRINGOP_OVERFLOW', 1)
835 if CHECK_CFLAGS(conf, ["-Wno-error=declaration-after-statement"]):
836 conf.define('HAVE_WNO_ERROR_DECLARATION_AFTER_STATEMENT', 1)
838 if not Options.options.disable_warnings_as_errors:
839 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
840 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
841 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=cast-align', testflags=True)
843 if Options.options.fatal_errors:
844 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
846 if Options.options.pedantic:
847 conf.ADD_CFLAGS('-W', testflags=True)
849 if (Options.options.address_sanitizer or
850 Options.options.undefined_sanitizer):
851 conf.ADD_CFLAGS('-g -O1', testflags=True)
852 if (Options.options.address_sanitizer
853 or Options.options.memory_sanitizer):
854 conf.ADD_CFLAGS('-fno-omit-frame-pointer', testflags=True)
855 if Options.options.address_sanitizer:
856 conf.ADD_CFLAGS('-fsanitize=address', testflags=True)
857 conf.ADD_LDFLAGS('-fsanitize=address', testflags=True)
858 conf.env['ADDRESS_SANITIZER'] = True
859 if Options.options.undefined_sanitizer:
860 conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True)
861 conf.ADD_CFLAGS('-fsanitize=null', testflags=True)
862 conf.ADD_CFLAGS('-fsanitize=alignment', testflags=True)
863 conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True)
864 conf.env['UNDEFINED_SANITIZER'] = True
866 # MemorySanitizer is only available if you build with clang
867 if Options.options.memory_sanitizer:
868 conf.ADD_CFLAGS('-g -O2', testflags=True)
869 conf.ADD_CFLAGS('-fsanitize=memory', testflags=True)
870 conf.ADD_CFLAGS('-fsanitize-memory-track-origins=2', testflags=True)
871 conf.ADD_LDFLAGS('-fsanitize=memory')
872 conf.env['MEMORY_SANITIZER'] = True
874 # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS}
875 # environment variables which are only used the for final build.
877 # The CFLAGS and LDFLAGS environment variables are also
878 # used for the configure checks which might impact their results.
880 # If these variables don't pass a smoke test, fail the configure
882 conf.add_os_flags('ADDITIONAL_CFLAGS')
883 if conf.env.ADDITIONAL_CFLAGS:
884 conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS'],
885 mandatory=True)
886 conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS'])
888 conf.add_os_flags('ADDITIONAL_LDFLAGS')
889 if conf.env.ADDITIONAL_LDFLAGS:
890 conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS'],
891 mandatory=True)
892 conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS'])
894 if path is None:
895 conf.write_config_header('default/config.h', top=True, remove=False)
896 else:
897 conf.write_config_header(os.path.join(conf.variant, path), remove=False)
898 for key in conf.env.define_key:
899 conf.undefine(key, from_env=False)
900 conf.env.define_key = []
901 conf.SAMBA_CROSS_CHECK_COMPLETE()
904 @conf
905 def CONFIG_PATH(conf, name, default):
906 '''setup a configurable path'''
907 if not name in conf.env:
908 if default[0] == '/':
909 conf.env[name] = default
910 else:
911 conf.env[name] = conf.env['PREFIX'] + default
913 @conf
914 def ADD_NAMED_CFLAGS(conf, name, 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 prereq_flags = TO_LIST(prereq_flags)
921 if testflags:
922 ok_flags=[]
923 for f in flags.split():
924 if CHECK_CFLAGS(conf, [f] + prereq_flags):
925 ok_flags.append(f)
926 flags = ok_flags
927 if not name in conf.env:
928 conf.env[name] = []
929 conf.env[name].extend(TO_LIST(flags))
931 @conf
932 def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=None):
933 '''add some CFLAGS to the command line
934 optionally set testflags to ensure all the flags work
936 if prereq_flags is None:
937 prereq_flags = []
938 ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
939 prereq_flags=prereq_flags)
941 @conf
942 def ADD_LDFLAGS(conf, flags, testflags=False):
943 '''add some LDFLAGS to the command line
944 optionally set testflags to ensure all the flags work
946 this will return the flags that are added, if any
948 if testflags:
949 ok_flags=[]
950 for f in flags.split():
951 if CHECK_LDFLAGS(conf, f):
952 ok_flags.append(f)
953 flags = ok_flags
954 if not 'EXTRA_LDFLAGS' in conf.env:
955 conf.env['EXTRA_LDFLAGS'] = []
956 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
957 return flags
960 @conf
961 def ADD_EXTRA_INCLUDES(conf, includes):
962 '''add some extra include directories to all builds'''
963 if not 'EXTRA_INCLUDES' in conf.env:
964 conf.env['EXTRA_INCLUDES'] = []
965 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
969 def CURRENT_CFLAGS(bld, target, cflags,
970 allow_warnings=False,
971 use_hostcc=False,
972 hide_symbols=False):
973 '''work out the current flags. local flags are added first'''
974 ret = []
975 if use_hostcc:
976 ret += ['-D_SAMBA_HOSTCC_']
977 ret += TO_LIST(cflags)
978 if not 'EXTRA_CFLAGS' in bld.env:
979 list = []
980 else:
981 list = bld.env['EXTRA_CFLAGS']
982 ret.extend(list)
983 if not allow_warnings and 'PICKY_CFLAGS' in bld.env:
984 list = bld.env['PICKY_CFLAGS']
985 ret.extend(list)
986 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
987 ret.append(bld.env.VISIBILITY_CFLAGS)
988 return ret
991 @conf
992 def CHECK_CC_ENV(conf):
993 """trim whitespaces from 'CC'.
994 The build farm sometimes puts a space at the start"""
995 if os.environ.get('CC'):
996 conf.env.CC = TO_LIST(os.environ.get('CC'))
999 @conf
1000 def SETUP_CONFIGURE_CACHE(conf, enable):
1001 '''enable/disable cache of configure results'''
1002 if enable:
1003 # when -C is chosen, we will use a private cache and will
1004 # not look into system includes. This roughly matches what
1005 # autoconf does with -C
1006 cache_path = os.path.join(conf.bldnode.abspath(), '.confcache')
1007 mkdir_p(cache_path)
1008 Options.cache_global = os.environ['WAFCACHE'] = cache_path
1009 else:
1010 # when -C is not chosen we will not cache configure checks
1011 # We set the recursion limit low to prevent waf from spending
1012 # a lot of time on the signatures of the files.
1013 Options.cache_global = os.environ['WAFCACHE'] = ''
1014 preproc.recursion_limit = 1
1015 # in either case we don't need to scan system includes
1016 preproc.go_absolute = False
1019 @conf
1020 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
1021 if (Options.options.address_sanitizer
1022 or Options.options.memory_sanitizer
1023 or Options.options.enable_libfuzzer):
1024 # Sanitizers can rely on symbols undefined at library link time and the
1025 # symbols used for fuzzers are only defined by compiler wrappers.
1026 return
1028 if not sys.platform.startswith("openbsd"):
1029 # we don't want any libraries or modules to rely on runtime
1030 # resolution of symbols
1031 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
1033 if (conf.env.undefined_ignore_ldflags == [] and
1034 conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'])):
1035 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']