WHATSNEW: Add release notes for Samba 3.6.17.
[Samba.git] / buildtools / wafsamba / samba_autoconf.py
blob174ca142102a038bfab7751dcf48ce469229fa58
1 # a waf tool to add autoconf-like macros to the configure section
3 import Build, os, sys, Options, preproc, Logs
4 import string
5 from Configure import conf
6 from samba_utils import *
7 import samba_cross
9 missing_headers = set()
11 ####################################################
12 # some autoconf like helpers, to make the transition
13 # to waf a bit easier for those used to autoconf
14 # m4 files
16 @runonce
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('CCDEFINES', d + '=' + str(v))
24 def hlist_to_string(conf, headers=None):
25 '''convert a headers list to a set of #include lines'''
26 hdrs=''
27 hlist = conf.env.hlist
28 if headers:
29 hlist = hlist[:]
30 hlist.extend(TO_LIST(headers))
31 for h in hlist:
32 hdrs += '#include <%s>\n' % h
33 return hdrs
36 @conf
37 def COMPOUND_START(conf, msg):
38 '''start a compound test'''
39 def null_check_message_1(self,*k,**kw):
40 return
41 def null_check_message_2(self,*k,**kw):
42 return
44 v = getattr(conf.env, 'in_compound', [])
45 if v != [] and v != 0:
46 conf.env.in_compound = v + 1
47 return
48 conf.check_message_1(msg)
49 conf.saved_check_message_1 = conf.check_message_1
50 conf.check_message_1 = null_check_message_1
51 conf.saved_check_message_2 = conf.check_message_2
52 conf.check_message_2 = null_check_message_2
53 conf.env.in_compound = 1
56 @conf
57 def COMPOUND_END(conf, result):
58 '''start a compound test'''
59 conf.env.in_compound -= 1
60 if conf.env.in_compound != 0:
61 return
62 conf.check_message_1 = conf.saved_check_message_1
63 conf.check_message_2 = conf.saved_check_message_2
64 p = conf.check_message_2
65 if result == True:
66 p('ok ')
67 elif result == False:
68 p('not found', 'YELLOW')
69 else:
70 p(result)
73 @feature('nolink')
74 def nolink(self):
75 '''using the nolink type in conf.check() allows us to avoid
76 the link stage of a test, thus speeding it up for tests
77 that where linking is not needed'''
78 pass
81 def CHECK_HEADER(conf, h, add_headers=False, lib=None):
82 '''check for a header'''
83 if h in missing_headers and lib is None:
84 return False
85 d = h.upper().replace('/', '_')
86 d = d.replace('.', '_')
87 d = d.replace('-', '_')
88 d = 'HAVE_%s' % d
89 if CONFIG_SET(conf, d):
90 if add_headers:
91 if not h in conf.env.hlist:
92 conf.env.hlist.append(h)
93 return True
95 (ccflags, ldflags) = library_flags(conf, lib)
97 hdrs = hlist_to_string(conf, headers=h)
98 ret = conf.check(fragment='%s\nint main(void) { return 0; }' % hdrs,
99 type='nolink',
100 execute=0,
101 ccflags=ccflags,
102 msg="Checking for header %s" % h)
103 if not ret:
104 missing_headers.add(h)
105 return False
107 conf.DEFINE(d, 1)
108 if add_headers and not h in conf.env.hlist:
109 conf.env.hlist.append(h)
110 return ret
113 @conf
114 def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None):
115 '''check for a list of headers
117 when together==True, then the headers accumulate within this test.
118 This is useful for interdependent headers
120 ret = True
121 if not add_headers and together:
122 saved_hlist = conf.env.hlist[:]
123 set_add_headers = True
124 else:
125 set_add_headers = add_headers
126 for hdr in TO_LIST(headers):
127 if not CHECK_HEADER(conf, hdr, set_add_headers, lib=lib):
128 ret = False
129 if not add_headers and together:
130 conf.env.hlist = saved_hlist
131 return ret
134 def header_list(conf, headers=None, lib=None):
135 '''form a list of headers which exist, as a string'''
136 hlist=[]
137 if headers is not None:
138 for h in TO_LIST(headers):
139 if CHECK_HEADER(conf, h, add_headers=False, lib=lib):
140 hlist.append(h)
141 return hlist_to_string(conf, headers=hlist)
144 @conf
145 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
146 '''check for a single type'''
147 if define is None:
148 define = 'HAVE_' + t.upper().replace(' ', '_')
149 if msg is None:
150 msg='Checking for %s' % t
151 ret = CHECK_CODE(conf, '%s _x' % t,
152 define,
153 execute=False,
154 headers=headers,
155 local_include=False,
156 msg=msg,
157 lib=lib,
158 link=False)
159 if not ret and alternate:
160 conf.DEFINE(t, alternate)
161 return ret
164 @conf
165 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
166 '''check for a list of types'''
167 ret = True
168 for t in TO_LIST(list):
169 if not CHECK_TYPE(conf, t, headers=headers,
170 define=define, alternate=alternate, lib=lib):
171 ret = False
172 return ret
175 @conf
176 def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
177 '''check for a single type with a header'''
178 return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
181 @conf
182 def CHECK_VARIABLE(conf, v, define=None, always=False,
183 headers=None, msg=None, lib=None):
184 '''check for a variable declaration (or define)'''
185 if define is None:
186 define = 'HAVE_%s' % v.upper()
188 if msg is None:
189 msg="Checking for variable %s" % v
191 return CHECK_CODE(conf,
192 # we need to make sure the compiler doesn't
193 # optimize it out...
195 #ifndef %s
196 void *_x; _x=(void *)&%s; return (int)_x;
197 #endif
198 return 0
199 ''' % (v, v),
200 execute=False,
201 link=False,
202 msg=msg,
203 local_include=False,
204 lib=lib,
205 headers=headers,
206 define=define,
207 always=always)
210 @conf
211 def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False):
212 '''check a list of variable declarations, using the HAVE_DECL_xxx form
213 of define
215 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
217 ret = True
218 for v in TO_LIST(vars):
219 if not reverse:
220 define='HAVE_DECL_%s' % v.upper()
221 else:
222 define='HAVE_%s_DECL' % v.upper()
223 if not CHECK_VARIABLE(conf, v,
224 define=define,
225 headers=headers,
226 msg='Checking for declaration of %s' % v,
227 always=always):
228 ret = False
229 return ret
232 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
233 '''check for a function'''
234 define='HAVE_%s' % f.upper()
236 ret = False
238 conf.COMPOUND_START('Checking for %s' % f)
240 if link is None or link == True:
241 ret = CHECK_CODE(conf,
242 # this is based on the autoconf strategy
244 #define %s __fake__%s
245 #ifdef HAVE_LIMITS_H
246 # include <limits.h>
247 #else
248 # include <assert.h>
249 #endif
250 #undef %s
251 #if defined __stub_%s || defined __stub___%s
252 #error "bad glibc stub"
253 #endif
254 extern char %s();
255 int main() { return %s(); }
256 ''' % (f, f, f, f, f, f, f),
257 execute=False,
258 link=True,
259 addmain=False,
260 add_headers=False,
261 define=define,
262 local_include=False,
263 lib=lib,
264 headers=headers,
265 msg='Checking for %s' % f)
267 if not ret:
268 ret = CHECK_CODE(conf,
269 # it might be a macro
270 # we need to make sure the compiler doesn't
271 # optimize it out...
272 'void *__x = (void *)%s; return (int)__x' % f,
273 execute=False,
274 link=True,
275 addmain=True,
276 add_headers=True,
277 define=define,
278 local_include=False,
279 lib=lib,
280 headers=headers,
281 msg='Checking for macro %s' % f)
283 if not ret and (link is None or link == False):
284 ret = CHECK_VARIABLE(conf, f,
285 define=define,
286 headers=headers,
287 msg='Checking for declaration of %s' % f)
288 conf.COMPOUND_END(ret)
289 return ret
292 @conf
293 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
294 '''check for a list of functions'''
295 ret = True
296 for f in TO_LIST(list):
297 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
298 ret = False
299 return ret
302 @conf
303 def CHECK_SIZEOF(conf, vars, headers=None, define=None):
304 '''check the size of a type'''
305 ret = True
306 for v in TO_LIST(vars):
307 v_define = define
308 if v_define is None:
309 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
310 if not CHECK_CODE(conf,
311 'printf("%%u", (unsigned)sizeof(%s))' % v,
312 define=v_define,
313 execute=True,
314 define_ret=True,
315 quote=False,
316 headers=headers,
317 local_include=False,
318 msg="Checking size of %s" % v):
319 ret = False
320 return ret
324 @conf
325 def CHECK_CODE(conf, code, define,
326 always=False, execute=False, addmain=True,
327 add_headers=True, mandatory=False,
328 headers=None, msg=None, cflags='', includes='# .',
329 local_include=True, lib=None, link=True,
330 define_ret=False, quote=False,
331 on_target=True):
332 '''check if some code compiles and/or runs'''
334 if CONFIG_SET(conf, define):
335 return True
337 if headers is not None:
338 CHECK_HEADERS(conf, headers=headers, lib=lib)
340 if add_headers:
341 hdrs = header_list(conf, headers=headers, lib=lib)
342 else:
343 hdrs = ''
344 if execute:
345 execute = 1
346 else:
347 execute = 0
349 defs = conf.get_config_header()
351 if addmain:
352 fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code)
353 else:
354 fragment='%s\n%s\n%s\n' % (defs, hdrs, code)
356 if msg is None:
357 msg="Checking for %s" % define
359 cflags = TO_LIST(cflags)
361 if local_include:
362 cflags.append('-I%s' % conf.curdir)
364 if not link:
365 type='nolink'
366 else:
367 type='cprogram'
369 uselib = TO_LIST(lib)
371 (ccflags, ldflags) = library_flags(conf, uselib)
373 cflags.extend(ccflags)
375 if on_target:
376 exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
377 else:
378 exec_args = []
380 conf.COMPOUND_START(msg)
382 ret = conf.check(fragment=fragment,
383 execute=execute,
384 define_name = define,
385 mandatory = mandatory,
386 ccflags=cflags,
387 ldflags=ldflags,
388 includes=includes,
389 uselib=uselib,
390 type=type,
391 msg=msg,
392 quote=quote,
393 exec_args=exec_args,
394 define_ret=define_ret)
395 if not ret and CONFIG_SET(conf, define):
396 # sometimes conf.check() returns false, but it
397 # sets the define. Maybe a waf bug?
398 ret = True
399 if ret:
400 if not define_ret:
401 conf.DEFINE(define, 1)
402 conf.COMPOUND_END(True)
403 else:
404 conf.COMPOUND_END(conf.env[define])
405 return True
406 if always:
407 conf.DEFINE(define, 0)
408 conf.COMPOUND_END(False)
409 return False
413 @conf
414 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
415 always=False, define=None, headers=None):
416 '''check for a structure member'''
417 if define is None:
418 define = 'HAVE_%s' % member.upper()
419 return CHECK_CODE(conf,
420 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
421 define,
422 execute=False,
423 link=False,
424 always=always,
425 headers=headers,
426 local_include=False,
427 msg="Checking for member %s in %s" % (member, structname))
430 @conf
431 def CHECK_CFLAGS(conf, cflags):
432 '''check if the given cflags are accepted by the compiler
434 return conf.check(fragment='int main(void) { return 0; }\n',
435 execute=0,
436 type='nolink',
437 ccflags=cflags,
438 msg="Checking compiler accepts %s" % cflags)
440 @conf
441 def CHECK_LDFLAGS(conf, ldflags):
442 '''check if the given ldflags are accepted by the linker
444 return conf.check(fragment='int main(void) { return 0; }\n',
445 execute=0,
446 ldflags=ldflags,
447 msg="Checking linker accepts %s" % ldflags)
450 @conf
451 def CONFIG_GET(conf, option):
452 '''return True if a configuration option was found'''
453 if (option in conf.env):
454 return conf.env[option]
455 else:
456 return None
458 @conf
459 def CONFIG_SET(conf, option):
460 '''return True if a configuration option was found'''
461 return (option in conf.env) and (conf.env[option] != ())
462 Build.BuildContext.CONFIG_SET = CONFIG_SET
463 Build.BuildContext.CONFIG_GET = CONFIG_GET
466 def library_flags(self, libs):
467 '''work out flags from pkg_config'''
468 ccflags = []
469 ldflags = []
470 for lib in TO_LIST(libs):
471 inc_path = getattr(self.env, 'CPPPATH_%s' % lib.upper(), [])
472 lib_path = getattr(self.env, 'LIBPATH_%s' % lib.upper(), [])
473 ccflags.extend(['-I%s' % i for i in inc_path])
474 ldflags.extend(['-L%s' % l for l in lib_path])
475 extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
476 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
477 ccflags.extend(extra_ccflags)
478 ldflags.extend(extra_ldflags)
479 if 'EXTRA_LDFLAGS' in self.env:
480 ldflags.extend(self.env['EXTRA_LDFLAGS'])
482 ccflags = unique_list(ccflags)
483 ldflags = unique_list(ldflags)
484 return (ccflags, ldflags)
487 @conf
488 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
489 '''check if a set of libraries exist as system libraries
491 returns the sublist of libs that do exist as a syslib or []
494 fragment= '''
495 int foo()
497 int v = 2;
498 return v*2;
501 ret = []
502 liblist = TO_LIST(libs)
503 for lib in liblist[:]:
504 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
505 ret.append(lib)
506 continue
508 (ccflags, ldflags) = library_flags(conf, lib)
509 if shlib:
510 res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
511 else:
512 res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
514 if not res:
515 if mandatory:
516 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
517 sys.exit(1)
518 if empty_decl:
519 # if it isn't a mandatory library, then remove it from dependency lists
520 if set_target:
521 SET_TARGET_TYPE(conf, lib, 'EMPTY')
522 else:
523 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
524 conf.env['LIB_' + lib.upper()] = lib
525 if set_target:
526 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
527 ret.append(lib)
529 return ret
533 @conf
534 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
535 headers=None, link=True, empty_decl=True, set_target=True):
537 check that the functions in 'list' are available in 'library'
538 if they are, then make that library available as a dependency
540 if the library is not available and mandatory==True, then
541 raise an error.
543 If the library is not available and mandatory==False, then
544 add the library to the list of dependencies to remove from
545 build rules
547 optionally check for the functions first in libc
549 remaining = TO_LIST(list)
550 liblist = TO_LIST(library)
552 # check if some already found
553 for f in remaining[:]:
554 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
555 remaining.remove(f)
557 # see if the functions are in libc
558 if checklibc:
559 for f in remaining[:]:
560 if CHECK_FUNC(conf, f, link=True, headers=headers):
561 remaining.remove(f)
563 if remaining == []:
564 for lib in liblist:
565 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
566 SET_TARGET_TYPE(conf, lib, 'EMPTY')
567 return True
569 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
570 for lib in liblist[:]:
571 if not lib in checklist and mandatory:
572 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
573 sys.exit(1)
575 ret = True
576 for f in remaining:
577 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
578 ret = False
580 return ret
583 @conf
584 def IN_LAUNCH_DIR(conf):
585 '''return True if this rule is being run from the launch directory'''
586 return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
587 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
590 @conf
591 def SAMBA_CONFIG_H(conf, path=None):
592 '''write out config.h in the right directory'''
593 # we don't want to produce a config.h in places like lib/replace
594 # when we are building projects that depend on lib/replace
595 if not IN_LAUNCH_DIR(conf):
596 return
598 if Options.options.developer:
599 # we add these here to ensure that -Wstrict-prototypes is not set during configure
600 conf.ADD_CFLAGS('-Wall -g -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Werror-implicit-function-declaration -Wformat=2 -Wno-format-y2k -Wmissing-prototypes',
601 testflags=True)
602 if os.getenv('TOPLEVEL_BUILD'):
603 conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
604 conf.env.DEVELOPER_MODE = True
606 if Options.options.picky_developer:
607 conf.ADD_CFLAGS('-Werror', testflags=True)
609 if Options.options.fatal_errors:
610 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
612 if Options.options.pedantic:
613 conf.ADD_CFLAGS('-W', testflags=True)
615 if path is None:
616 conf.write_config_header('config.h', top=True)
617 else:
618 conf.write_config_header(path)
619 conf.SAMBA_CROSS_CHECK_COMPLETE()
622 @conf
623 def CONFIG_PATH(conf, name, default):
624 '''setup a configurable path'''
625 if not name in conf.env:
626 if default[0] == '/':
627 conf.env[name] = default
628 else:
629 conf.env[name] = conf.env['PREFIX'] + default
631 @conf
632 def ADD_CFLAGS(conf, flags, testflags=False):
633 '''add some CFLAGS to the command line
634 optionally set testflags to ensure all the flags work
636 if testflags:
637 ok_flags=[]
638 for f in flags.split():
639 if CHECK_CFLAGS(conf, f):
640 ok_flags.append(f)
641 flags = ok_flags
642 if not 'EXTRA_CFLAGS' in conf.env:
643 conf.env['EXTRA_CFLAGS'] = []
644 conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
646 @conf
647 def ADD_LDFLAGS(conf, flags, testflags=False):
648 '''add some LDFLAGS to the command line
649 optionally set testflags to ensure all the flags work
651 this will return the flags that are added, if any
653 if testflags:
654 ok_flags=[]
655 for f in flags.split():
656 if CHECK_LDFLAGS(conf, f):
657 ok_flags.append(f)
658 flags = ok_flags
659 if not 'EXTRA_LDFLAGS' in conf.env:
660 conf.env['EXTRA_LDFLAGS'] = []
661 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
662 return flags
665 @conf
666 def ADD_EXTRA_INCLUDES(conf, includes):
667 '''add some extra include directories to all builds'''
668 if not 'EXTRA_INCLUDES' in conf.env:
669 conf.env['EXTRA_INCLUDES'] = []
670 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
674 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
675 '''work out the current flags. local flags are added first'''
676 if not 'EXTRA_CFLAGS' in bld.env:
677 list = []
678 else:
679 list = bld.env['EXTRA_CFLAGS'];
680 ret = TO_LIST(cflags)
681 ret.extend(list)
682 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
683 ret.append('-fvisibility=hidden')
684 return ret
687 @conf
688 def CHECK_CC_ENV(conf):
689 """trim whitespaces from 'CC'.
690 The build farm sometimes puts a space at the start"""
691 if os.environ.get('CC'):
692 conf.env.CC = TO_LIST(os.environ.get('CC'))
693 if len(conf.env.CC) == 1:
694 # make for nicer logs if just a single command
695 conf.env.CC = conf.env.CC[0]
698 @conf
699 def SETUP_CONFIGURE_CACHE(conf, enable):
700 '''enable/disable cache of configure results'''
701 if enable:
702 # when -C is chosen, we will use a private cache and will
703 # not look into system includes. This roughtly matches what
704 # autoconf does with -C
705 cache_path = os.path.join(conf.blddir, '.confcache')
706 mkdir_p(cache_path)
707 Options.cache_global = os.environ['WAFCACHE'] = cache_path
708 else:
709 # when -C is not chosen we will not cache configure checks
710 # We set the recursion limit low to prevent waf from spending
711 # a lot of time on the signatures of the files.
712 Options.cache_global = os.environ['WAFCACHE'] = ''
713 preproc.recursion_limit = 1
714 # in either case we don't need to scan system includes
715 preproc.go_absolute = False