1 # a waf tool to add autoconf-like macros to the configure section
3 import Build, os, sys, Options, preproc, Logs
5 from Configure import conf
6 from samba_utils import *
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
18 def DEFINE(conf, d, v, add_to_cflags=False, quote=False):
19 '''define a config option'''
20 conf.define(d, v, quote=quote)
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'''
27 hlist = conf.env.hlist
30 hlist.extend(TO_LIST(headers))
32 hdrs += '#include <%s>\n' % h
37 def COMPOUND_START(conf, msg):
38 '''start a compound test'''
39 def null_check_message_1(self,*k,**kw):
41 def null_check_message_2(self,*k,**kw):
44 v = getattr(conf.env, 'in_compound', [])
45 if v != [] and v != 0:
46 conf.env.in_compound = v + 1
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
57 def COMPOUND_END(conf, result):
58 '''start a compound test'''
59 conf.env.in_compound -= 1
60 if conf.env.in_compound != 0:
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
68 p('not found', 'YELLOW')
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'''
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:
85 d = h.upper().replace('/', '_')
86 d = d.replace('.', '_')
87 d = d.replace('-', '_')
89 if CONFIG_SET(conf, d):
91 if not h in conf.env.hlist:
92 conf.env.hlist.append(h)
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,
102 msg="Checking for header %s" % h)
104 missing_headers.add(h)
108 if add_headers and not h in conf.env.hlist:
109 conf.env.hlist.append(h)
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
121 if not add_headers and together:
122 saved_hlist = conf.env.hlist[:]
123 set_add_headers = True
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):
129 if not add_headers and together:
130 conf.env.hlist = saved_hlist
134 def header_list(conf, headers=None, lib=None):
135 '''form a list of headers which exist, as a string'''
137 if headers is not None:
138 for h in TO_LIST(headers):
139 if CHECK_HEADER(conf, h, add_headers=False, lib=lib):
141 return hlist_to_string(conf, headers=hlist)
145 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
146 '''check for a single type'''
148 define = 'HAVE_' + t.upper().replace(' ', '_')
150 msg='Checking for %s' % t
151 ret = CHECK_CODE(conf, '%s _x' % t,
159 if not ret and alternate:
160 conf.DEFINE(t, alternate)
165 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
166 '''check for a list of types'''
168 for t in TO_LIST(list):
169 if not CHECK_TYPE(conf, t, headers=headers,
170 define=define, alternate=alternate, lib=lib):
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)
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)'''
186 define = 'HAVE_%s' % v.upper()
189 msg="Checking for variable %s" % v
191 return CHECK_CODE(conf,
192 # we need to make sure the compiler doesn't
196 void *_x; _x=(void *)&%s; return (int)_x;
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
215 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
218 for v in TO_LIST(vars):
220 define='HAVE_DECL_%s' % v.upper()
222 define='HAVE_%s_DECL' % v.upper()
223 if not CHECK_VARIABLE(conf, v,
226 msg='Checking for declaration of %s' % v,
232 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
233 '''check for a function'''
234 define='HAVE_%s' % f.upper()
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
251 #if defined __stub_%s || defined __stub___%s
252 #error "bad glibc stub"
255 int main() { return %s(); }
256 ''' % (f, f, f, f, f, f, f),
265 msg='Checking for %s' % f)
268 ret = CHECK_CODE(conf,
269 # it might be a macro
270 # we need to make sure the compiler doesn't
272 'void *__x = (void *)%s; return (int)__x' % f,
281 msg='Checking for macro %s' % f)
283 if not ret and (link is None or link == False):
284 ret = CHECK_VARIABLE(conf, f,
287 msg='Checking for declaration of %s' % f)
288 conf.COMPOUND_END(ret)
293 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
294 '''check for a list of functions'''
296 for f in TO_LIST(list):
297 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
303 def CHECK_SIZEOF(conf, vars, headers=None, define=None):
304 '''check the size of a type'''
306 for v in TO_LIST(vars):
309 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
310 if not CHECK_CODE(conf,
311 'printf("%%u", (unsigned)sizeof(%s))' % v,
318 msg="Checking size of %s" % v):
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,
332 '''check if some code compiles and/or runs'''
334 if CONFIG_SET(conf, define):
337 if headers is not None:
338 CHECK_HEADERS(conf, headers=headers, lib=lib)
341 hdrs = header_list(conf, headers=headers, lib=lib)
349 defs = conf.get_config_header()
352 fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code)
354 fragment='%s\n%s\n%s\n' % (defs, hdrs, code)
357 msg="Checking for %s" % define
359 cflags = TO_LIST(cflags)
362 cflags.append('-I%s' % conf.curdir)
369 uselib = TO_LIST(lib)
371 (ccflags, ldflags) = library_flags(conf, uselib)
373 cflags.extend(ccflags)
376 exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
380 conf.COMPOUND_START(msg)
382 ret = conf.check(fragment=fragment,
384 define_name = define,
385 mandatory = mandatory,
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?
401 conf.DEFINE(define, 1)
402 conf.COMPOUND_END(True)
404 conf.COMPOUND_END(conf.env[define])
407 conf.DEFINE(define, 0)
408 conf.COMPOUND_END(False)
414 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
415 always=False, define=None, headers=None):
416 '''check for a structure member'''
418 define = 'HAVE_%s' % member.upper()
419 return CHECK_CODE(conf,
420 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
427 msg="Checking for member %s in %s" % (member, structname))
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',
438 msg="Checking compiler accepts %s" % cflags)
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',
447 msg="Checking linker accepts %s" % ldflags)
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]
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'''
470 for lib in TO_LIST(libs):
471 # note that we do not add the -I and -L in here, as that is added by the waf
472 # core. Adding it here would just change the order that it is put on the link line
473 # which can cause system paths to be added before internal libraries
474 extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
475 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
476 ccflags.extend(extra_ccflags)
477 ldflags.extend(extra_ldflags)
478 if 'EXTRA_LDFLAGS' in self.env:
479 ldflags.extend(self.env['EXTRA_LDFLAGS'])
481 ccflags = unique_list(ccflags)
482 ldflags = unique_list(ldflags)
483 return (ccflags, ldflags)
487 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
488 '''check if a set of libraries exist as system libraries
490 returns the sublist of libs that do exist as a syslib or []
501 liblist = TO_LIST(libs)
502 for lib in liblist[:]:
503 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
507 (ccflags, ldflags) = library_flags(conf, lib)
509 res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
511 res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
515 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
518 # if it isn't a mandatory library, then remove it from dependency lists
520 SET_TARGET_TYPE(conf, lib, 'EMPTY')
522 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
523 conf.env['LIB_' + lib.upper()] = lib
525 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
533 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
534 headers=None, link=True, empty_decl=True, set_target=True):
536 check that the functions in 'list' are available in 'library'
537 if they are, then make that library available as a dependency
539 if the library is not available and mandatory==True, then
542 If the library is not available and mandatory==False, then
543 add the library to the list of dependencies to remove from
546 optionally check for the functions first in libc
548 remaining = TO_LIST(list)
549 liblist = TO_LIST(library)
551 # check if some already found
552 for f in remaining[:]:
553 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
556 # see if the functions are in libc
558 for f in remaining[:]:
559 if CHECK_FUNC(conf, f, link=True, headers=headers):
564 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
565 SET_TARGET_TYPE(conf, lib, 'EMPTY')
568 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
569 for lib in liblist[:]:
570 if not lib in checklist and mandatory:
571 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
576 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
583 def IN_LAUNCH_DIR(conf):
584 '''return True if this rule is being run from the launch directory'''
585 return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
586 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
590 def SAMBA_CONFIG_H(conf, path=None):
591 '''write out config.h in the right directory'''
592 # we don't want to produce a config.h in places like lib/replace
593 # when we are building projects that depend on lib/replace
594 if not IN_LAUNCH_DIR(conf):
597 if Options.options.developer:
598 # we add these here to ensure that -Wstrict-prototypes is not set during configure
599 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',
601 conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
602 conf.env.DEVELOPER_MODE = True
604 if Options.options.picky_developer:
605 conf.ADD_CFLAGS('-Werror', testflags=True)
607 if Options.options.fatal_errors:
608 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
610 if Options.options.pedantic:
611 conf.ADD_CFLAGS('-W', testflags=True)
614 conf.write_config_header('config.h', top=True)
616 conf.write_config_header(path)
617 conf.SAMBA_CROSS_CHECK_COMPLETE()
621 def CONFIG_PATH(conf, name, default):
622 '''setup a configurable path'''
623 if not name in conf.env:
624 if default[0] == '/':
625 conf.env[name] = default
627 conf.env[name] = conf.env['PREFIX'] + default
630 def ADD_CFLAGS(conf, flags, testflags=False):
631 '''add some CFLAGS to the command line
632 optionally set testflags to ensure all the flags work
636 for f in flags.split():
637 if CHECK_CFLAGS(conf, f):
640 if not 'EXTRA_CFLAGS' in conf.env:
641 conf.env['EXTRA_CFLAGS'] = []
642 conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
645 def ADD_LDFLAGS(conf, flags, testflags=False):
646 '''add some LDFLAGS to the command line
647 optionally set testflags to ensure all the flags work
649 this will return the flags that are added, if any
653 for f in flags.split():
654 if CHECK_LDFLAGS(conf, f):
657 if not 'EXTRA_LDFLAGS' in conf.env:
658 conf.env['EXTRA_LDFLAGS'] = []
659 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
664 def ADD_EXTRA_INCLUDES(conf, includes):
665 '''add some extra include directories to all builds'''
666 if not 'EXTRA_INCLUDES' in conf.env:
667 conf.env['EXTRA_INCLUDES'] = []
668 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
672 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
673 '''work out the current flags. local flags are added first'''
674 if not 'EXTRA_CFLAGS' in bld.env:
677 list = bld.env['EXTRA_CFLAGS'];
678 ret = TO_LIST(cflags)
680 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
681 ret.append('-fvisibility=hidden')
686 def CHECK_CC_ENV(conf):
687 """trim whitespaces from 'CC'.
688 The build farm sometimes puts a space at the start"""
689 if os.environ.get('CC'):
690 conf.env.CC = TO_LIST(os.environ.get('CC'))
691 if len(conf.env.CC) == 1:
692 # make for nicer logs if just a single command
693 conf.env.CC = conf.env.CC[0]
697 def SETUP_CONFIGURE_CACHE(conf, enable):
698 '''enable/disable cache of configure results'''
700 # when -C is chosen, we will use a private cache and will
701 # not look into system includes. This roughtly matches what
702 # autoconf does with -C
703 cache_path = os.path.join(conf.blddir, '.confcache')
705 Options.cache_global = os.environ['WAFCACHE'] = cache_path
707 # when -C is not chosen we will not cache configure checks
708 # We set the recursion limit low to prevent waf from spending
709 # a lot of time on the signatures of the files.
710 Options.cache_global = os.environ['WAFCACHE'] = ''
711 preproc.recursion_limit = 1
712 # in either case we don't need to scan system includes
713 preproc.go_absolute = False
717 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
718 # we don't want any libraries or modules to rely on runtime
719 # resolution of symbols
720 if sys.platform != "openbsd4":
721 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
723 if sys.platform != "openbsd4" and conf.env.undefined_ignore_ldflags == []:
724 if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
725 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']