1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

build: rewrote the autoconf-like macros to be more consistent

This also brings them much closer to the behaviour of autoconf
This commit is contained in:
Andrew Tridgell 2010-03-23 09:29:19 +11:00
parent 98d16cbec0
commit f95ca1afc9

View File

@ -5,6 +5,8 @@ import string
from Configure import conf
from samba_utils import *
missing_headers = set()
####################################################
# some autoconf like helpers, to make the transition
# to waf a bit easier for those used to autoconf
@ -18,105 +20,130 @@ def DEFINE(conf, d, v, add_to_cflags=False):
if add_to_cflags:
conf.env.append_value('CCDEFINES', d + '=' + str(v))
def hlist_to_string(conf, headers=None):
'''convert a headers list to a set of #include lines'''
hdrs=''
hlist = conf.env.hlist
if headers:
hlist = hlist[:]
hlist.extend(TO_LIST(headers))
for h in hlist:
hdrs += '#include <%s>\n' % h
return hdrs
def CHECK_HEADER(conf, h, add_headers=True):
@feature('nolink')
def nolink(self):
'''using the nolink type in conf.check() allows us to avoid
the link stage of a test, thus speeding it up for tests
that where linking is not needed'''
pass
def CHECK_HEADER(conf, h, add_headers=False):
'''check for a header'''
d = 'HAVE_%s' % string.replace(h.upper(), '/', '_')
if h in missing_headers:
return False
d = h.upper().replace('/', '_')
d = d.replace('.', '_')
d = 'HAVE_%s' % d
if CONFIG_SET(conf, d):
if add_headers:
conf.env.hlist.append(h)
conf.env.hlist = unique_list(conf.env.hlist)
if not h in conf.env.hlist:
conf.env.hlist.append(h)
return True
ret = conf.check(header_name=h)
if ret and add_headers:
hdrs = hlist_to_string(conf, headers=h)
ret = conf.check(fragment='%s\nint main(void) { return 0; }' % hdrs,
type='nolink',
execute=0,
msg="Checking for header %s" % h)
if not ret:
missing_headers.add(h)
return False
conf.DEFINE(d, 1)
if add_headers and not h in conf.env.hlist:
conf.env.hlist.append(h)
conf.env.hlist = unique_list(conf.env.hlist)
return ret
@conf
def CHECK_HEADERS(conf, list, add_headers=True):
def CHECK_HEADERS(conf, headers, add_headers=False):
'''check for a list of headers'''
ret = True
for hdr in TO_LIST(list):
for hdr in TO_LIST(headers):
if not CHECK_HEADER(conf, hdr, add_headers):
ret = False
return ret
@conf
def CHECK_TYPES(conf, list):
'''check for a list of types'''
ret = True
lst = TO_LIST(list)
for t in TO_LIST(list):
if not conf.check(type_name=t, header_name=conf.env.hlist):
ret = False
return ret
@conf
def CHECK_TYPE_IN(conf, t, hdr, define=None):
'''check for a type in a specific header'''
if conf.check(header_name=hdr):
if define is None:
ret = conf.check(type_name=t, header_name=hdr)
else:
ret = conf.check(type_name=t, header_name=hdr, define_name=define)
return ret
return False
def header_list(conf, headers=None):
'''form a list of headers which exist, as a string'''
hlist=[]
if headers is not None:
for h in TO_LIST(headers):
if CHECK_HEADER(conf, h, add_headers=False):
hlist.append(h)
return hlist_to_string(conf, headers=hlist)
@conf
def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None):
'''check for a type with an alternate'''
if headers is None:
headers = conf.env.hlist
if define is not None:
ret = conf.check(type_name=t, header_name=headers, define_name=define)
else:
ret = conf.check(type_name=t, header_name=headers)
if not ret and alternate is not None:
'''check for a single type'''
if define is None:
define = 'HAVE_' + t.upper().replace(' ', '_')
ret = CHECK_CODE(conf, '%s _x' % t,
define,
execute=False,
headers=headers,
msg='Checking for %s' % t,
local_include=False,
link=False)
if not ret and alternate:
conf.DEFINE(t, alternate)
return ret
@conf
def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None):
'''check for a list of types'''
ret = True
for t in TO_LIST(list):
if not CHECK_TYPE(conf, t, headers=headers, define=define, alternate=alternate):
ret = False
return ret
@conf
def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
'''check for a single type with a header'''
return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
@conf
def CHECK_VARIABLE(conf, v, define=None, always=False, headers=None, msg=None):
'''check for a variable declaration (or define)'''
hdrs=''
if headers is not None:
hlist = TO_LIST(headers)
else:
hlist = conf.env.hlist
for h in hlist:
hdrs += '#include <%s>\n' % h
if define is None:
define = 'HAVE_%s' % v.upper()
if CONFIG_SET(conf, define):
return True
if msg is None:
msg="Checking for variable %s" % v
if conf.check(fragment=
'''
%s
int main(void) {
#ifndef %s
void *_x; _x=(void *)&%s;
#endif
return 0;
}
''' % (hdrs, v, v),
execute=0,
msg=msg):
conf.DEFINE(define, 1)
return True
elif always:
conf.DEFINE(define, 0)
return False
return CHECK_CODE(conf,
'''
#ifndef %s
void *_x; _x=(void *)&%s;
#endif
return 0
''' % (v, v),
execute=False,
link=False,
msg=msg,
local_include=False,
headers=headers,
define=define,
always=always)
@conf
def CHECK_DECLS(conf, vars, reverse=False, headers=None):
@ -139,29 +166,50 @@ def CHECK_DECLS(conf, vars, reverse=False, headers=None):
return ret
def CHECK_FUNC(conf, f, checklink=False, header=''):
def CHECK_FUNC(conf, f, link=None, lib='c', headers=None):
'''check for a function'''
hlist = conf.env.hlist[:]
for h in TO_LIST(header):
if CHECK_HEADER(conf, h, add_headers=False):
hlist.append(h)
define='HAVE_%s' % f.upper()
if CONFIG_SET(conf, define):
return True
if checklink:
return CHECK_CODE(conf, 'void *x = (void *)%s' % f,
execute=False, define=define,
msg='Checking for %s' % f)
return conf.check_cc(function_name=f, header_name=hlist)
# there are two ways to find a function. The first is
# to see if there is a declaration of the function, the
# 2nd is to try and link a program that calls the function
# unfortunately both strategies have problems.
# the 'check the declaration' approach works fine as long
# as the function has a declaraion in a header. If there is
# no header declaration we can get a false negative.
# The link method works fine as long as the compiler
# doesn't have a builtin for the function, which could cause
# a false negative due to mismatched parameters
# so to be sure, we need to try both
ret = False
if link is None or link == True:
ret = CHECK_CODE(conf,
'int main(void) { extern void %s(void); %s(); return 0; }' % (f, f),
execute=False,
link=True,
addmain=False,
add_headers=False,
define=define,
local_include=False,
lib=lib,
headers=headers,
msg='Checking for %s' % f)
if not ret and (link is None or link == False):
ret = CHECK_VARIABLE(conf, f,
define=define,
headers=headers,
msg='Checking for declaration of %s' % f)
return ret
@conf
def CHECK_FUNCS(conf, list, checklink=False, header=''):
def CHECK_FUNCS(conf, list, link=None, lib='c', headers=None):
'''check for a list of functions'''
ret = True
for f in TO_LIST(list):
if not CHECK_FUNC(conf, f, checklink=checklink, header=header):
if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
ret = False
return ret
@ -169,47 +217,44 @@ def CHECK_FUNCS(conf, list, checklink=False, header=''):
@conf
def CHECK_SIZEOF(conf, vars, headers=None, define=None):
'''check the size of a type'''
hdrs=''
if headers is not None:
hlist = TO_LIST(headers)
else:
hlist = conf.env.hlist
for h in hlist:
hdrs += '#include <%s>\n' % h
ret = True
for v in TO_LIST(vars):
if define is None:
define_name = 'SIZEOF_%s' % string.replace(v.upper(), ' ', '_')
else:
define_name = define
conf.check(fragment=
'''
%s
int main(void) {
printf("%%u\\n", (unsigned)sizeof(%s));
return 0;
}
''' % (hdrs, v),
execute=1,
define_ret=True,
define_name=define_name,
quote=False,
msg="Checking size of %s" % v)
v_define = define
if v_define is None:
v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
if not CHECK_CODE(conf,
'printf("%%u\\n", (unsigned)sizeof(%s))' % v,
define=v_define,
execute=True,
define_ret=True,
quote=False,
headers=headers,
local_include=False,
msg="Checking size of %s" % v):
ret = False
return ret
@conf
def CHECK_CODE(conf, code, define,
always=False, execute=False, addmain=True, mandatory=False,
always=False, execute=False, addmain=True,
add_headers=True, mandatory=False,
headers=None, msg=None, cflags='', includes='# .',
local_include=True, lib='c'):
local_include=True, lib='c', link=True,
define_ret=False, quote=False):
'''check if some code compiles and/or runs'''
hdrs=''
if headers is not None:
hlist = TO_LIST(headers)
else:
hlist = conf.env.hlist
for h in hlist:
hdrs += '#include <%s>\n' % h
if CONFIG_SET(conf, define):
return True
if headers is not None:
CHECK_HEADERS(conf, headers=headers)
if add_headers:
hdrs = header_list(conf, headers=headers)
else:
hdrs = ''
if execute:
execute = 1
else:
@ -231,6 +276,11 @@ def CHECK_CODE(conf, code, define,
if local_include:
cflags += ' -I%s' % conf.curdir
if not link:
type='nolink'
else:
type='cprogram'
if conf.check(fragment=fragment,
execute=execute,
define_name = define,
@ -238,8 +288,12 @@ def CHECK_CODE(conf, code, define,
ccflags=TO_LIST(cflags),
includes=includes,
lib=lib, # how do I make this conditional, so I can avoid the -lc?
msg=msg):
conf.DEFINE(define, 1)
type=type,
msg=msg,
quote=quote,
define_ret=define_ret):
if not define_ret:
conf.DEFINE(define, 1)
return True
if always:
conf.DEFINE(define, 0)
@ -251,43 +305,27 @@ def CHECK_CODE(conf, code, define,
def CHECK_STRUCTURE_MEMBER(conf, structname, member,
always=False, define=None, headers=None):
'''check for a structure member'''
hdrs=''
if headers is not None:
hlist = TO_LIST(headers)
else:
hlist = conf.env.hlist
for h in hlist:
hdrs += '#include <%s>\n' % h
if define is None:
define = 'HAVE_%s' % member.upper()
if conf.check(fragment=
'''
%s
int main(void) {
%s s;
void *_x; _x=(void *)&s.%s;
return 0;
}
''' % (hdrs, structname, member),
execute=0,
msg="Checking for member %s in %s" % (member, structname)):
conf.DEFINE(define, 1)
return True
elif always:
conf.DEFINE(define, 0)
return False
return CHECK_CODE(conf,
'%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
define,
execute=False,
link=False,
always=always,
headers=headers,
local_include=False,
msg="Checking for member %s in %s" % (member, structname))
@conf
def CHECK_CFLAGS(conf, cflags, variable):
'''check if the given cflags are accepted by the compiler'''
if conf.check(fragment='int main(void) { return 0; }',
execute=0,
ccflags=cflags,
msg="Checking compiler accepts %s" % cflags):
conf.env[variable] = cflags
return True
return False
def CHECK_CFLAGS(conf, cflags):
'''check if the given cflags are accepted by the compiler
'''
return conf.check(fragment='int main(void) { return 0; }',
execute=0,
ccflags=cflags,
msg="Checking compiler accepts %s" % cflags)
#################################################
@ -298,6 +336,29 @@ def CONFIG_SET(conf, option):
Build.BuildContext.CONFIG_SET = CONFIG_SET
@conf
def CHECK_LIB(conf, libs):
'''check if a set of libraries exist'''
liblist = TO_LIST(library)
ret = True
for lib in liblist[:]:
if GET_TARGET_TYPE(conf, lib):
continue
if not conf.check(lib=lib, uselib_store=lib):
conf.ASSERT(not mandatory,
"Mandatory library '%s' not found for functions '%s'" % (lib, list))
# if it isn't a mandatory library, then remove it from dependency lists
SET_TARGET_TYPE(conf, lib, 'EMPTY')
ret = False
else:
conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
conf.env['LIB_' + lib.upper()] = lib
LOCAL_CACHE_SET(conf, 'TARGET_TYPE', lib, 'SYSLIB')
return ret
###########################################################
# check that the functions in 'list' are available in 'library'
# if they are, then make that library available as a dependency
@ -311,15 +372,10 @@ Build.BuildContext.CONFIG_SET = CONFIG_SET
#
# optionally check for the functions first in libc
@conf
def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, header=''):
def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, headers=None, link=None):
remaining = TO_LIST(list)
liblist = TO_LIST(library)
hlist = conf.env.hlist[:]
for h in TO_LIST(header):
if CHECK_HEADER(conf, h, add_headers=False):
hlist.append(h)
# check if some already found
for f in remaining[:]:
if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
@ -328,7 +384,7 @@ def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, header
# see if the functions are in libc
if checklibc:
for f in remaining[:]:
if CHECK_FUNC(conf, f, checklink=True, header=header):
if CHECK_FUNC(conf, f, link=True, headers=headers):
remaining.remove(f)
if remaining == []:
@ -348,7 +404,7 @@ def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, header
SET_TARGET_TYPE(conf, lib, 'EMPTY')
ret = False
else:
conf.define('HAVE_LIB%s' % string.replace(lib.upper(),'-','_'), 1)
conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
conf.env['LIB_' + lib.upper()] = lib
LOCAL_CACHE_SET(conf, 'TARGET_TYPE', lib, 'SYSLIB')
@ -357,7 +413,7 @@ def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, header
ret = True
for f in remaining:
if not conf.check_cc(function_name=f, lib=liblist, header_name=hlist):
if not CHECK_FUNC(conf, f, lib=' '.join(liblist), headers=headers, link=link):
ret = False
return ret
@ -370,6 +426,7 @@ def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None):
return False
return conf.CHECK_CODE('%s; void *_x = (void *)%s' % (prototype, function),
define=define,
local_include=False,
msg='Checking C prototype for %s' % function)
@ -439,6 +496,7 @@ def CHECK_RPATH_SUPPORT(conf):
return conf.CHECK_CODE('int x',
define='HAVE_RPATH_SUPPORT',
execute=True,
local_include=False,
msg='Checking for rpath support',
cflags='-Wl,-rpath=.')