Improve the VFS Makefile so that it is easier for use out of tree but still works...
[Samba/gebeck_regimport.git] / buildtools / wafsamba / samba_autoconf.py
blob4da5df86a07f3bc668241ffcd8339b9e8be837dd
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, cpppath) = library_flags(conf, lib)
97 hdrs = hlist_to_string(conf, headers=h)
98 if lib is None:
99 lib = ""
100 ret = conf.check(fragment='%s\nint main(void) { return 0; }' % hdrs,
101 type='nolink',
102 execute=0,
103 ccflags=ccflags,
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):
150 '''check for a single type'''
151 if define is None:
152 define = 'HAVE_' + t.upper().replace(' ', '_')
153 if msg is None:
154 msg='Checking for %s' % t
155 ret = CHECK_CODE(conf, '%s _x' % t,
156 define,
157 execute=False,
158 headers=headers,
159 local_include=False,
160 msg=msg,
161 lib=lib,
162 link=False)
163 if not ret and alternate:
164 conf.DEFINE(t, alternate)
165 return ret
168 @conf
169 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
170 '''check for a list of types'''
171 ret = True
172 for t in TO_LIST(list):
173 if not CHECK_TYPE(conf, t, headers=headers,
174 define=define, alternate=alternate, lib=lib):
175 ret = False
176 return ret
179 @conf
180 def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
181 '''check for a single type with a header'''
182 return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
185 @conf
186 def CHECK_VARIABLE(conf, v, define=None, always=False,
187 headers=None, msg=None, lib=None):
188 '''check for a variable declaration (or define)'''
189 if define is None:
190 define = 'HAVE_%s' % v.upper()
192 if msg is None:
193 msg="Checking for variable %s" % v
195 return CHECK_CODE(conf,
196 # we need to make sure the compiler doesn't
197 # optimize it out...
199 #ifndef %s
200 void *_x; _x=(void *)&%s; return (int)_x;
201 #endif
202 return 0
203 ''' % (v, v),
204 execute=False,
205 link=False,
206 msg=msg,
207 local_include=False,
208 lib=lib,
209 headers=headers,
210 define=define,
211 always=always)
214 @conf
215 def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False):
216 '''check a list of variable declarations, using the HAVE_DECL_xxx form
217 of define
219 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
221 ret = True
222 for v in TO_LIST(vars):
223 if not reverse:
224 define='HAVE_DECL_%s' % v.upper()
225 else:
226 define='HAVE_%s_DECL' % v.upper()
227 if not CHECK_VARIABLE(conf, v,
228 define=define,
229 headers=headers,
230 msg='Checking for declaration of %s' % v,
231 always=always):
232 ret = False
233 return ret
236 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
237 '''check for a function'''
238 define='HAVE_%s' % f.upper()
240 ret = False
242 conf.COMPOUND_START('Checking for %s' % f)
244 if link is None or link == True:
245 ret = CHECK_CODE(conf,
246 # this is based on the autoconf strategy
248 #define %s __fake__%s
249 #ifdef HAVE_LIMITS_H
250 # include <limits.h>
251 #else
252 # include <assert.h>
253 #endif
254 #undef %s
255 #if defined __stub_%s || defined __stub___%s
256 #error "bad glibc stub"
257 #endif
258 extern char %s();
259 int main() { return %s(); }
260 ''' % (f, f, f, f, f, f, f),
261 execute=False,
262 link=True,
263 addmain=False,
264 add_headers=False,
265 define=define,
266 local_include=False,
267 lib=lib,
268 headers=headers,
269 msg='Checking for %s' % f)
271 if not ret:
272 ret = CHECK_CODE(conf,
273 # it might be a macro
274 # we need to make sure the compiler doesn't
275 # optimize it out...
276 'void *__x = (void *)%s; return (int)__x' % f,
277 execute=False,
278 link=True,
279 addmain=True,
280 add_headers=True,
281 define=define,
282 local_include=False,
283 lib=lib,
284 headers=headers,
285 msg='Checking for macro %s' % f)
287 if not ret and (link is None or link == False):
288 ret = CHECK_VARIABLE(conf, f,
289 define=define,
290 headers=headers,
291 msg='Checking for declaration of %s' % f)
292 conf.COMPOUND_END(ret)
293 return ret
296 @conf
297 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
298 '''check for a list of functions'''
299 ret = True
300 for f in TO_LIST(list):
301 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
302 ret = False
303 return ret
306 @conf
307 def CHECK_SIZEOF(conf, vars, headers=None, define=None):
308 '''check the size of a type'''
309 ret = True
310 for v in TO_LIST(vars):
311 v_define = define
312 if v_define is None:
313 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
314 if not CHECK_CODE(conf,
315 'printf("%%u", (unsigned)sizeof(%s))' % v,
316 define=v_define,
317 execute=True,
318 define_ret=True,
319 quote=False,
320 headers=headers,
321 local_include=False,
322 msg="Checking size of %s" % v):
323 ret = False
324 return ret
328 @conf
329 def CHECK_CODE(conf, code, define,
330 always=False, execute=False, addmain=True,
331 add_headers=True, mandatory=False,
332 headers=None, msg=None, cflags='', includes='# .',
333 local_include=True, lib=None, link=True,
334 define_ret=False, quote=False,
335 on_target=True):
336 '''check if some code compiles and/or runs'''
338 if CONFIG_SET(conf, define):
339 return True
341 if headers is not None:
342 CHECK_HEADERS(conf, headers=headers, lib=lib)
344 if add_headers:
345 hdrs = header_list(conf, headers=headers, lib=lib)
346 else:
347 hdrs = ''
348 if execute:
349 execute = 1
350 else:
351 execute = 0
353 defs = conf.get_config_header()
355 if addmain:
356 fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code)
357 else:
358 fragment='%s\n%s\n%s\n' % (defs, hdrs, code)
360 if msg is None:
361 msg="Checking for %s" % define
363 cflags = TO_LIST(cflags)
365 if local_include:
366 cflags.append('-I%s' % conf.curdir)
368 if not link:
369 type='nolink'
370 else:
371 type='cprogram'
373 uselib = TO_LIST(lib)
375 (ccflags, ldflags, cpppath) = library_flags(conf, uselib)
377 includes = TO_LIST(includes)
378 includes.extend(cpppath)
380 uselib = [l.upper() for l in uselib]
382 cflags.extend(ccflags)
384 if on_target:
385 exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
386 else:
387 exec_args = []
389 conf.COMPOUND_START(msg)
391 ret = conf.check(fragment=fragment,
392 execute=execute,
393 define_name = define,
394 mandatory = mandatory,
395 ccflags=cflags,
396 ldflags=ldflags,
397 includes=includes,
398 uselib=uselib,
399 type=type,
400 msg=msg,
401 quote=quote,
402 exec_args=exec_args,
403 define_ret=define_ret)
404 if not ret and CONFIG_SET(conf, define):
405 # sometimes conf.check() returns false, but it
406 # sets the define. Maybe a waf bug?
407 ret = True
408 if ret:
409 if not define_ret:
410 conf.DEFINE(define, 1)
411 conf.COMPOUND_END(True)
412 else:
413 conf.COMPOUND_END(conf.env[define])
414 return True
415 if always:
416 conf.DEFINE(define, 0)
417 conf.COMPOUND_END(False)
418 return False
422 @conf
423 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
424 always=False, define=None, headers=None):
425 '''check for a structure member'''
426 if define is None:
427 define = 'HAVE_%s' % member.upper()
428 return CHECK_CODE(conf,
429 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
430 define,
431 execute=False,
432 link=False,
433 always=always,
434 headers=headers,
435 local_include=False,
436 msg="Checking for member %s in %s" % (member, structname))
439 @conf
440 def CHECK_CFLAGS(conf, cflags):
441 '''check if the given cflags are accepted by the compiler
443 return conf.check(fragment='int main(void) { return 0; }\n',
444 execute=0,
445 type='nolink',
446 ccflags=cflags,
447 msg="Checking compiler accepts %s" % cflags)
449 @conf
450 def CHECK_LDFLAGS(conf, ldflags):
451 '''check if the given ldflags are accepted by the linker
453 return conf.check(fragment='int main(void) { return 0; }\n',
454 execute=0,
455 ldflags=ldflags,
456 msg="Checking linker accepts %s" % ldflags)
459 @conf
460 def CONFIG_GET(conf, option):
461 '''return True if a configuration option was found'''
462 if (option in conf.env):
463 return conf.env[option]
464 else:
465 return None
467 @conf
468 def CONFIG_SET(conf, option):
469 '''return True if a configuration option was found'''
470 return (option in conf.env) and (conf.env[option] != ())
471 Build.BuildContext.CONFIG_SET = CONFIG_SET
472 Build.BuildContext.CONFIG_GET = CONFIG_GET
475 def library_flags(self, libs):
476 '''work out flags from pkg_config'''
477 ccflags = []
478 ldflags = []
479 cpppath = []
480 for lib in TO_LIST(libs):
481 # note that we do not add the -I and -L in here, as that is added by the waf
482 # core. Adding it here would just change the order that it is put on the link line
483 # which can cause system paths to be added before internal libraries
484 extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
485 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
486 extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), []))
487 ccflags.extend(extra_ccflags)
488 ldflags.extend(extra_ldflags)
489 cpppath.extend(extra_cpppath)
490 if 'EXTRA_LDFLAGS' in self.env:
491 ldflags.extend(self.env['EXTRA_LDFLAGS'])
493 ccflags = unique_list(ccflags)
494 ldflags = unique_list(ldflags)
495 cpppath = unique_list(cpppath)
496 return (ccflags, ldflags, cpppath)
499 @conf
500 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
501 '''check if a set of libraries exist as system libraries
503 returns the sublist of libs that do exist as a syslib or []
506 fragment= '''
507 int foo()
509 int v = 2;
510 return v*2;
513 ret = []
514 liblist = TO_LIST(libs)
515 for lib in liblist[:]:
516 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
517 ret.append(lib)
518 continue
520 (ccflags, ldflags, cpppath) = library_flags(conf, lib)
521 if shlib:
522 res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags, uselib=lib.upper())
523 else:
524 res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags, uselib=lib.upper())
526 if not res:
527 if mandatory:
528 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
529 sys.exit(1)
530 if empty_decl:
531 # if it isn't a mandatory library, then remove it from dependency lists
532 if set_target:
533 SET_TARGET_TYPE(conf, lib, 'EMPTY')
534 else:
535 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
536 conf.env['LIB_' + lib.upper()] = lib
537 if set_target:
538 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
539 ret.append(lib)
541 return ret
545 @conf
546 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
547 headers=None, link=True, empty_decl=True, set_target=True):
549 check that the functions in 'list' are available in 'library'
550 if they are, then make that library available as a dependency
552 if the library is not available and mandatory==True, then
553 raise an error.
555 If the library is not available and mandatory==False, then
556 add the library to the list of dependencies to remove from
557 build rules
559 optionally check for the functions first in libc
561 remaining = TO_LIST(list)
562 liblist = TO_LIST(library)
564 # check if some already found
565 for f in remaining[:]:
566 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
567 remaining.remove(f)
569 # see if the functions are in libc
570 if checklibc:
571 for f in remaining[:]:
572 if CHECK_FUNC(conf, f, link=True, headers=headers):
573 remaining.remove(f)
575 if remaining == []:
576 for lib in liblist:
577 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
578 SET_TARGET_TYPE(conf, lib, 'EMPTY')
579 return True
581 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
582 for lib in liblist[:]:
583 if not lib in checklist and mandatory:
584 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
585 sys.exit(1)
587 ret = True
588 for f in remaining:
589 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
590 ret = False
592 return ret
595 @conf
596 def IN_LAUNCH_DIR(conf):
597 '''return True if this rule is being run from the launch directory'''
598 return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
599 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
602 @conf
603 def SAMBA_CONFIG_H(conf, path=None):
604 '''write out config.h in the right directory'''
605 # we don't want to produce a config.h in places like lib/replace
606 # when we are building projects that depend on lib/replace
607 if not IN_LAUNCH_DIR(conf):
608 return
610 if Options.options.debug:
611 conf.ADD_CFLAGS('-g',
612 testflags=True)
614 if Options.options.developer:
615 # we add these here to ensure that -Wstrict-prototypes is not set during configure
616 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 -fno-common',
617 testflags=True)
618 conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
619 conf.env.DEVELOPER_MODE = True
621 if Options.options.picky_developer:
622 conf.ADD_CFLAGS('-Werror', testflags=True)
624 if Options.options.fatal_errors:
625 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
627 if Options.options.pedantic:
628 conf.ADD_CFLAGS('-W', testflags=True)
630 if path is None:
631 conf.write_config_header('config.h', top=True)
632 else:
633 conf.write_config_header(path)
634 conf.SAMBA_CROSS_CHECK_COMPLETE()
637 @conf
638 def CONFIG_PATH(conf, name, default):
639 '''setup a configurable path'''
640 if not name in conf.env:
641 if default[0] == '/':
642 conf.env[name] = default
643 else:
644 conf.env[name] = conf.env['PREFIX'] + default
646 @conf
647 def ADD_CFLAGS(conf, flags, testflags=False):
648 '''add some CFLAGS to the command line
649 optionally set testflags to ensure all the flags work
651 if testflags:
652 ok_flags=[]
653 for f in flags.split():
654 if CHECK_CFLAGS(conf, f):
655 ok_flags.append(f)
656 flags = ok_flags
657 if not 'EXTRA_CFLAGS' in conf.env:
658 conf.env['EXTRA_CFLAGS'] = []
659 conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
661 @conf
662 def ADD_LDFLAGS(conf, flags, testflags=False):
663 '''add some LDFLAGS to the command line
664 optionally set testflags to ensure all the flags work
666 this will return the flags that are added, if any
668 if testflags:
669 ok_flags=[]
670 for f in flags.split():
671 if CHECK_LDFLAGS(conf, f):
672 ok_flags.append(f)
673 flags = ok_flags
674 if not 'EXTRA_LDFLAGS' in conf.env:
675 conf.env['EXTRA_LDFLAGS'] = []
676 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
677 return flags
680 @conf
681 def ADD_EXTRA_INCLUDES(conf, includes):
682 '''add some extra include directories to all builds'''
683 if not 'EXTRA_INCLUDES' in conf.env:
684 conf.env['EXTRA_INCLUDES'] = []
685 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
689 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
690 '''work out the current flags. local flags are added first'''
691 if not 'EXTRA_CFLAGS' in bld.env:
692 list = []
693 else:
694 list = bld.env['EXTRA_CFLAGS'];
695 ret = TO_LIST(cflags)
696 ret.extend(list)
697 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
698 ret.append('-fvisibility=hidden')
699 return ret
702 @conf
703 def CHECK_CC_ENV(conf):
704 """trim whitespaces from 'CC'.
705 The build farm sometimes puts a space at the start"""
706 if os.environ.get('CC'):
707 conf.env.CC = TO_LIST(os.environ.get('CC'))
708 if len(conf.env.CC) == 1:
709 # make for nicer logs if just a single command
710 conf.env.CC = conf.env.CC[0]
713 @conf
714 def SETUP_CONFIGURE_CACHE(conf, enable):
715 '''enable/disable cache of configure results'''
716 if enable:
717 # when -C is chosen, we will use a private cache and will
718 # not look into system includes. This roughtly matches what
719 # autoconf does with -C
720 cache_path = os.path.join(conf.blddir, '.confcache')
721 mkdir_p(cache_path)
722 Options.cache_global = os.environ['WAFCACHE'] = cache_path
723 else:
724 # when -C is not chosen we will not cache configure checks
725 # We set the recursion limit low to prevent waf from spending
726 # a lot of time on the signatures of the files.
727 Options.cache_global = os.environ['WAFCACHE'] = ''
728 preproc.recursion_limit = 1
729 # in either case we don't need to scan system includes
730 preproc.go_absolute = False
733 @conf
734 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
735 # we don't want any libraries or modules to rely on runtime
736 # resolution of symbols
737 if sys.platform != "openbsd4" and sys.platform != "openbsd5":
738 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
740 if sys.platform != "openbsd4" and sys.platform != "openbsd5" and conf.env.undefined_ignore_ldflags == []:
741 if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
742 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']