pidl/NDR/Parser: simplify logic in DeclareArrayVariables*()
[Samba.git] / buildtools / wafsamba / samba_autoconf.py
blob2bb86c786c2ee2275bb3d0a7a71533d6dbeb6f26
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 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 uselib=lib.upper(),
105 msg="Checking for header %s" % h)
106 if not ret:
107 missing_headers.add(h)
108 return False
110 conf.DEFINE(d, 1)
111 if add_headers and not h in conf.env.hlist:
112 conf.env.hlist.append(h)
113 return ret
116 @conf
117 def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None):
118 '''check for a list of headers
120 when together==True, then the headers accumulate within this test.
121 This is useful for interdependent headers
123 ret = True
124 if not add_headers and together:
125 saved_hlist = conf.env.hlist[:]
126 set_add_headers = True
127 else:
128 set_add_headers = add_headers
129 for hdr in TO_LIST(headers):
130 if not CHECK_HEADER(conf, hdr, set_add_headers, lib=lib):
131 ret = False
132 if not add_headers and together:
133 conf.env.hlist = saved_hlist
134 return ret
137 def header_list(conf, headers=None, lib=None):
138 '''form a list of headers which exist, as a string'''
139 hlist=[]
140 if headers is not None:
141 for h in TO_LIST(headers):
142 if CHECK_HEADER(conf, h, add_headers=False, lib=lib):
143 hlist.append(h)
144 return hlist_to_string(conf, headers=hlist)
147 @conf
148 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
149 '''check for a single type'''
150 if define is None:
151 define = 'HAVE_' + t.upper().replace(' ', '_')
152 if msg is None:
153 msg='Checking for %s' % t
154 ret = CHECK_CODE(conf, '%s _x' % t,
155 define,
156 execute=False,
157 headers=headers,
158 local_include=False,
159 msg=msg,
160 lib=lib,
161 link=False)
162 if not ret and alternate:
163 conf.DEFINE(t, alternate)
164 return ret
167 @conf
168 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
169 '''check for a list of types'''
170 ret = True
171 for t in TO_LIST(list):
172 if not CHECK_TYPE(conf, t, headers=headers,
173 define=define, alternate=alternate, lib=lib):
174 ret = False
175 return ret
178 @conf
179 def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
180 '''check for a single type with a header'''
181 return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
184 @conf
185 def CHECK_VARIABLE(conf, v, define=None, always=False,
186 headers=None, msg=None, lib=None):
187 '''check for a variable declaration (or define)'''
188 if define is None:
189 define = 'HAVE_%s' % v.upper()
191 if msg is None:
192 msg="Checking for variable %s" % v
194 return CHECK_CODE(conf,
195 # we need to make sure the compiler doesn't
196 # optimize it out...
198 #ifndef %s
199 void *_x; _x=(void *)&%s; return (int)_x;
200 #endif
201 return 0
202 ''' % (v, v),
203 execute=False,
204 link=False,
205 msg=msg,
206 local_include=False,
207 lib=lib,
208 headers=headers,
209 define=define,
210 always=always)
213 @conf
214 def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False):
215 '''check a list of variable declarations, using the HAVE_DECL_xxx form
216 of define
218 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
220 ret = True
221 for v in TO_LIST(vars):
222 if not reverse:
223 define='HAVE_DECL_%s' % v.upper()
224 else:
225 define='HAVE_%s_DECL' % v.upper()
226 if not CHECK_VARIABLE(conf, v,
227 define=define,
228 headers=headers,
229 msg='Checking for declaration of %s' % v,
230 always=always):
231 ret = False
232 return ret
235 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
236 '''check for a function'''
237 define='HAVE_%s' % f.upper()
239 ret = False
241 conf.COMPOUND_START('Checking for %s' % f)
243 if link is None or link == True:
244 ret = CHECK_CODE(conf,
245 # this is based on the autoconf strategy
247 #define %s __fake__%s
248 #ifdef HAVE_LIMITS_H
249 # include <limits.h>
250 #else
251 # include <assert.h>
252 #endif
253 #undef %s
254 #if defined __stub_%s || defined __stub___%s
255 #error "bad glibc stub"
256 #endif
257 extern char %s();
258 int main() { return %s(); }
259 ''' % (f, f, f, f, f, f, f),
260 execute=False,
261 link=True,
262 addmain=False,
263 add_headers=False,
264 define=define,
265 local_include=False,
266 lib=lib,
267 headers=headers,
268 msg='Checking for %s' % f)
270 if not ret:
271 ret = CHECK_CODE(conf,
272 # it might be a macro
273 # we need to make sure the compiler doesn't
274 # optimize it out...
275 'void *__x = (void *)%s; return (int)__x' % f,
276 execute=False,
277 link=True,
278 addmain=True,
279 add_headers=True,
280 define=define,
281 local_include=False,
282 lib=lib,
283 headers=headers,
284 msg='Checking for macro %s' % f)
286 if not ret and (link is None or link == False):
287 ret = CHECK_VARIABLE(conf, f,
288 define=define,
289 headers=headers,
290 msg='Checking for declaration of %s' % f)
291 conf.COMPOUND_END(ret)
292 return ret
295 @conf
296 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
297 '''check for a list of functions'''
298 ret = True
299 for f in TO_LIST(list):
300 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
301 ret = False
302 return ret
305 @conf
306 def CHECK_SIZEOF(conf, vars, headers=None, define=None):
307 '''check the size of a type'''
308 ret = True
309 for v in TO_LIST(vars):
310 v_define = define
311 if v_define is None:
312 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
313 if not CHECK_CODE(conf,
314 'printf("%%u", (unsigned)sizeof(%s))' % v,
315 define=v_define,
316 execute=True,
317 define_ret=True,
318 quote=False,
319 headers=headers,
320 local_include=False,
321 msg="Checking size of %s" % v):
322 ret = False
323 return ret
327 @conf
328 def CHECK_CODE(conf, code, define,
329 always=False, execute=False, addmain=True,
330 add_headers=True, mandatory=False,
331 headers=None, msg=None, cflags='', includes='# .',
332 local_include=True, lib=None, link=True,
333 define_ret=False, quote=False,
334 on_target=True):
335 '''check if some code compiles and/or runs'''
337 if CONFIG_SET(conf, define):
338 return True
340 if headers is not None:
341 CHECK_HEADERS(conf, headers=headers, lib=lib)
343 if add_headers:
344 hdrs = header_list(conf, headers=headers, lib=lib)
345 else:
346 hdrs = ''
347 if execute:
348 execute = 1
349 else:
350 execute = 0
352 defs = conf.get_config_header()
354 if addmain:
355 fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code)
356 else:
357 fragment='%s\n%s\n%s\n' % (defs, hdrs, code)
359 if msg is None:
360 msg="Checking for %s" % define
362 cflags = TO_LIST(cflags)
364 if local_include:
365 cflags.append('-I%s' % conf.curdir)
367 if not link:
368 type='nolink'
369 else:
370 type='cprogram'
372 uselib = TO_LIST(lib)
374 (ccflags, ldflags) = library_flags(conf, uselib)
376 uselib = [l.upper() for l in uselib]
378 cflags.extend(ccflags)
380 if on_target:
381 exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
382 else:
383 exec_args = []
385 conf.COMPOUND_START(msg)
387 ret = conf.check(fragment=fragment,
388 execute=execute,
389 define_name = define,
390 mandatory = mandatory,
391 ccflags=cflags,
392 ldflags=ldflags,
393 includes=includes,
394 uselib=uselib,
395 type=type,
396 msg=msg,
397 quote=quote,
398 exec_args=exec_args,
399 define_ret=define_ret)
400 if not ret and CONFIG_SET(conf, define):
401 # sometimes conf.check() returns false, but it
402 # sets the define. Maybe a waf bug?
403 ret = True
404 if ret:
405 if not define_ret:
406 conf.DEFINE(define, 1)
407 conf.COMPOUND_END(True)
408 else:
409 conf.COMPOUND_END(conf.env[define])
410 return True
411 if always:
412 conf.DEFINE(define, 0)
413 conf.COMPOUND_END(False)
414 return False
418 @conf
419 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
420 always=False, define=None, headers=None):
421 '''check for a structure member'''
422 if define is None:
423 define = 'HAVE_%s' % member.upper()
424 return CHECK_CODE(conf,
425 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
426 define,
427 execute=False,
428 link=False,
429 always=always,
430 headers=headers,
431 local_include=False,
432 msg="Checking for member %s in %s" % (member, structname))
435 @conf
436 def CHECK_CFLAGS(conf, cflags):
437 '''check if the given cflags are accepted by the compiler
439 return conf.check(fragment='int main(void) { return 0; }\n',
440 execute=0,
441 type='nolink',
442 ccflags=cflags,
443 msg="Checking compiler accepts %s" % cflags)
445 @conf
446 def CHECK_LDFLAGS(conf, ldflags):
447 '''check if the given ldflags are accepted by the linker
449 return conf.check(fragment='int main(void) { return 0; }\n',
450 execute=0,
451 ldflags=ldflags,
452 msg="Checking linker accepts %s" % ldflags)
455 @conf
456 def CONFIG_GET(conf, option):
457 '''return True if a configuration option was found'''
458 if (option in conf.env):
459 return conf.env[option]
460 else:
461 return None
463 @conf
464 def CONFIG_SET(conf, option):
465 '''return True if a configuration option was found'''
466 return (option in conf.env) and (conf.env[option] != ())
467 Build.BuildContext.CONFIG_SET = CONFIG_SET
468 Build.BuildContext.CONFIG_GET = CONFIG_GET
471 def library_flags(self, libs):
472 '''work out flags from pkg_config'''
473 ccflags = []
474 ldflags = []
475 for lib in TO_LIST(libs):
476 # note that we do not add the -I and -L in here, as that is added by the waf
477 # core. Adding it here would just change the order that it is put on the link line
478 # which can cause system paths to be added before internal libraries
479 extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
480 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
481 ccflags.extend(extra_ccflags)
482 ldflags.extend(extra_ldflags)
483 if 'EXTRA_LDFLAGS' in self.env:
484 ldflags.extend(self.env['EXTRA_LDFLAGS'])
486 ccflags = unique_list(ccflags)
487 ldflags = unique_list(ldflags)
488 return (ccflags, ldflags)
491 @conf
492 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
493 '''check if a set of libraries exist as system libraries
495 returns the sublist of libs that do exist as a syslib or []
498 fragment= '''
499 int foo()
501 int v = 2;
502 return v*2;
505 ret = []
506 liblist = TO_LIST(libs)
507 for lib in liblist[:]:
508 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
509 ret.append(lib)
510 continue
512 (ccflags, ldflags) = library_flags(conf, lib)
513 if shlib:
514 res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags, uselib=lib.upper())
515 else:
516 res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags, uselib=lib.upper())
518 if not res:
519 if mandatory:
520 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
521 sys.exit(1)
522 if empty_decl:
523 # if it isn't a mandatory library, then remove it from dependency lists
524 if set_target:
525 SET_TARGET_TYPE(conf, lib, 'EMPTY')
526 else:
527 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
528 conf.env['LIB_' + lib.upper()] = lib
529 if set_target:
530 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
531 ret.append(lib)
533 return ret
537 @conf
538 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
539 headers=None, link=True, empty_decl=True, set_target=True):
541 check that the functions in 'list' are available in 'library'
542 if they are, then make that library available as a dependency
544 if the library is not available and mandatory==True, then
545 raise an error.
547 If the library is not available and mandatory==False, then
548 add the library to the list of dependencies to remove from
549 build rules
551 optionally check for the functions first in libc
553 remaining = TO_LIST(list)
554 liblist = TO_LIST(library)
556 # check if some already found
557 for f in remaining[:]:
558 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
559 remaining.remove(f)
561 # see if the functions are in libc
562 if checklibc:
563 for f in remaining[:]:
564 if CHECK_FUNC(conf, f, link=True, headers=headers):
565 remaining.remove(f)
567 if remaining == []:
568 for lib in liblist:
569 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
570 SET_TARGET_TYPE(conf, lib, 'EMPTY')
571 return True
573 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
574 for lib in liblist[:]:
575 if not lib in checklist and mandatory:
576 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
577 sys.exit(1)
579 ret = True
580 for f in remaining:
581 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
582 ret = False
584 return ret
587 @conf
588 def IN_LAUNCH_DIR(conf):
589 '''return True if this rule is being run from the launch directory'''
590 return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
591 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
594 @conf
595 def SAMBA_CONFIG_H(conf, path=None):
596 '''write out config.h in the right directory'''
597 # we don't want to produce a config.h in places like lib/replace
598 # when we are building projects that depend on lib/replace
599 if not IN_LAUNCH_DIR(conf):
600 return
602 if Options.options.developer:
603 # we add these here to ensure that -Wstrict-prototypes is not set during configure
604 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',
605 testflags=True)
606 conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
607 conf.env.DEVELOPER_MODE = True
609 if Options.options.picky_developer:
610 conf.ADD_CFLAGS('-Werror', testflags=True)
612 if Options.options.fatal_errors:
613 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
615 if Options.options.pedantic:
616 conf.ADD_CFLAGS('-W', testflags=True)
618 if path is None:
619 conf.write_config_header('config.h', top=True)
620 else:
621 conf.write_config_header(path)
622 conf.SAMBA_CROSS_CHECK_COMPLETE()
625 @conf
626 def CONFIG_PATH(conf, name, default):
627 '''setup a configurable path'''
628 if not name in conf.env:
629 if default[0] == '/':
630 conf.env[name] = default
631 else:
632 conf.env[name] = conf.env['PREFIX'] + default
634 @conf
635 def ADD_CFLAGS(conf, flags, testflags=False):
636 '''add some CFLAGS to the command line
637 optionally set testflags to ensure all the flags work
639 if testflags:
640 ok_flags=[]
641 for f in flags.split():
642 if CHECK_CFLAGS(conf, f):
643 ok_flags.append(f)
644 flags = ok_flags
645 if not 'EXTRA_CFLAGS' in conf.env:
646 conf.env['EXTRA_CFLAGS'] = []
647 conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
649 @conf
650 def ADD_LDFLAGS(conf, flags, testflags=False):
651 '''add some LDFLAGS to the command line
652 optionally set testflags to ensure all the flags work
654 this will return the flags that are added, if any
656 if testflags:
657 ok_flags=[]
658 for f in flags.split():
659 if CHECK_LDFLAGS(conf, f):
660 ok_flags.append(f)
661 flags = ok_flags
662 if not 'EXTRA_LDFLAGS' in conf.env:
663 conf.env['EXTRA_LDFLAGS'] = []
664 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
665 return flags
668 @conf
669 def ADD_EXTRA_INCLUDES(conf, includes):
670 '''add some extra include directories to all builds'''
671 if not 'EXTRA_INCLUDES' in conf.env:
672 conf.env['EXTRA_INCLUDES'] = []
673 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
677 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
678 '''work out the current flags. local flags are added first'''
679 if not 'EXTRA_CFLAGS' in bld.env:
680 list = []
681 else:
682 list = bld.env['EXTRA_CFLAGS'];
683 ret = TO_LIST(cflags)
684 ret.extend(list)
685 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
686 ret.append('-fvisibility=hidden')
687 return ret
690 @conf
691 def CHECK_CC_ENV(conf):
692 """trim whitespaces from 'CC'.
693 The build farm sometimes puts a space at the start"""
694 if os.environ.get('CC'):
695 conf.env.CC = TO_LIST(os.environ.get('CC'))
696 if len(conf.env.CC) == 1:
697 # make for nicer logs if just a single command
698 conf.env.CC = conf.env.CC[0]
701 @conf
702 def SETUP_CONFIGURE_CACHE(conf, enable):
703 '''enable/disable cache of configure results'''
704 if enable:
705 # when -C is chosen, we will use a private cache and will
706 # not look into system includes. This roughtly matches what
707 # autoconf does with -C
708 cache_path = os.path.join(conf.blddir, '.confcache')
709 mkdir_p(cache_path)
710 Options.cache_global = os.environ['WAFCACHE'] = cache_path
711 else:
712 # when -C is not chosen we will not cache configure checks
713 # We set the recursion limit low to prevent waf from spending
714 # a lot of time on the signatures of the files.
715 Options.cache_global = os.environ['WAFCACHE'] = ''
716 preproc.recursion_limit = 1
717 # in either case we don't need to scan system includes
718 preproc.go_absolute = False
721 @conf
722 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
723 # we don't want any libraries or modules to rely on runtime
724 # resolution of symbols
725 if sys.platform != "openbsd4" and sys.platform != "openbsd5":
726 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
728 if sys.platform != "openbsd4" and sys.platform != "openbsd5" and conf.env.undefined_ignore_ldflags == []:
729 if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
730 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']