2010-03-25 01:56:57 +03:00
# a set of config tests that use the samba_autoconf functions
# to test for commonly needed configuration options
2010-03-28 10:24:05 +04:00
2015-10-31 16:39:35 +03:00
import os , shutil , re
2015-10-27 22:46:46 +03:00
import Build , Configure , Utils , Options , Logs
2010-03-25 15:53:10 +03:00
from Configure import conf
2015-10-27 22:46:46 +03:00
from samba_utils import TO_LIST , ADD_LD_LIBRARY_PATH
2010-03-25 01:56:57 +03:00
2012-05-17 16:49:08 +04:00
def add_option ( self , * k , * * kw ) :
''' syntax help: provide the " match " attribute to opt.add_option() so that folders can be added to specific config tests '''
match = kw . get ( ' match ' , [ ] )
if match :
del kw [ ' match ' ]
opt = self . parser . add_option ( * k , * * kw )
opt . match = match
return opt
Options . Handler . add_option = add_option
@conf
def check ( self , * k , * * kw ) :
''' Override the waf defaults to inject --with-directory options '''
if not ' env ' in kw :
kw [ ' env ' ] = self . env . copy ( )
2017-02-20 20:30:48 +03:00
# match the configuration test with specific options, for example:
2012-05-17 16:49:08 +04:00
# --with-libiconv -> Options.options.iconv_open -> "Checking for library iconv"
additional_dirs = [ ]
if ' msg ' in kw :
msg = kw [ ' msg ' ]
for x in Options . Handler . parser . parser . option_list :
if getattr ( x , ' match ' , None ) and msg in x . match :
d = getattr ( Options . options , x . dest , ' ' )
if d :
additional_dirs . append ( d )
# we add the additional dirs twice: once for the test data, and again if the compilation test suceeds below
def add_options_dir ( dirs , env ) :
for x in dirs :
if not x in env . CPPPATH :
env . CPPPATH = [ os . path . join ( x , ' include ' ) ] + env . CPPPATH
if not x in env . LIBPATH :
env . LIBPATH = [ os . path . join ( x , ' lib ' ) ] + env . LIBPATH
add_options_dir ( additional_dirs , kw [ ' env ' ] )
self . validate_c ( kw )
self . check_message_1 ( kw [ ' msg ' ] )
ret = None
try :
ret = self . run_c_code ( * k , * * kw )
2018-02-14 01:19:49 +03:00
except Configure . ConfigurationError as e :
2012-05-17 16:49:08 +04:00
self . check_message_2 ( kw [ ' errmsg ' ] , ' YELLOW ' )
if ' mandatory ' in kw and kw [ ' mandatory ' ] :
if Logs . verbose > 1 :
raise
else :
self . fatal ( ' the configuration failed (see %r ) ' % self . log . name )
else :
kw [ ' success ' ] = ret
self . check_message_2 ( self . ret_msg ( kw [ ' okmsg ' ] , kw ) )
# success! keep the CPPPATH/LIBPATH
add_options_dir ( additional_dirs , self . env )
self . post_check ( * k , * * kw )
if not kw . get ( ' execute ' , False ) :
return ret == 0
return ret
2010-03-25 01:56:57 +03:00
@conf
def CHECK_ICONV ( conf , define = ' HAVE_NATIVE_ICONV ' ) :
''' check if the iconv library is installed
optionally pass a define '''
if conf . CHECK_FUNCS_IN ( ' iconv_open ' , ' iconv ' , checklibc = True , headers = ' iconv.h ' ) :
conf . DEFINE ( define , 1 )
return True
return False
@conf
def CHECK_LARGEFILE ( conf , define = ' HAVE_LARGEFILE ' ) :
''' see what we need for largefile support '''
2012-04-05 02:25:13 +04:00
getconf_cflags = conf . CHECK_COMMAND ( [ ' getconf ' , ' LFS_CFLAGS ' ] ) ;
if getconf_cflags is not False :
if ( conf . CHECK_CODE ( ' return !(sizeof(off_t) >= 8) ' ,
define = ' WORKING_GETCONF_LFS_CFLAGS ' ,
execute = True ,
cflags = getconf_cflags ,
msg = ' Checking getconf large file support flags work ' ) ) :
conf . ADD_CFLAGS ( getconf_cflags )
getconf_cflags_list = TO_LIST ( getconf_cflags )
for flag in getconf_cflags_list :
if flag [ : 2 ] == " -D " :
flag_split = flag [ 2 : ] . split ( ' = ' )
if len ( flag_split ) == 1 :
conf . DEFINE ( flag_split [ 0 ] , ' 1 ' )
else :
conf . DEFINE ( flag_split [ 0 ] , flag_split [ 1 ] )
2010-03-25 01:56:57 +03:00
if conf . CHECK_CODE ( ' return !(sizeof(off_t) >= 8) ' ,
define ,
execute = True ,
2012-04-05 02:25:13 +04:00
msg = ' Checking for large file support without additional flags ' ) :
2010-03-25 01:56:57 +03:00
return True
2012-04-05 02:25:13 +04:00
2010-03-25 01:56:57 +03:00
if conf . CHECK_CODE ( ' return !(sizeof(off_t) >= 8) ' ,
define ,
execute = True ,
cflags = ' -D_FILE_OFFSET_BITS=64 ' ,
msg = ' Checking for -D_FILE_OFFSET_BITS=64 ' ) :
conf . DEFINE ( ' _FILE_OFFSET_BITS ' , 64 )
return True
2012-06-08 00:43:43 +04:00
if conf . CHECK_CODE ( ' return !(sizeof(off_t) >= 8) ' ,
define ,
execute = True ,
cflags = ' -D_LARGE_FILES ' ,
msg = ' Checking for -D_LARGE_FILES ' ) :
conf . DEFINE ( ' _LARGE_FILES ' , 1 )
return True
2010-03-25 01:56:57 +03:00
return False
@conf
2010-06-18 00:41:57 +04:00
def CHECK_C_PROTOTYPE ( conf , function , prototype , define , headers = None , msg = None ) :
2010-03-25 01:56:57 +03:00
''' verify that a C prototype matches the one on the current system '''
if not conf . CHECK_DECLS ( function , headers = headers ) :
return False
2010-06-18 00:41:57 +04:00
if not msg :
msg = ' Checking C prototype for %s ' % function
2010-03-25 01:56:57 +03:00
return conf . CHECK_CODE ( ' %s ; void *_x = (void *) %s ' % ( prototype , function ) ,
define = define ,
local_include = False ,
headers = headers ,
2010-03-30 06:19:46 +04:00
link = False ,
execute = False ,
2010-06-18 00:41:57 +04:00
msg = msg )
2010-03-25 01:56:57 +03:00
@conf
2010-03-26 09:55:25 +03:00
def CHECK_CHARSET_EXISTS ( conf , charset , outcharset = ' UCS-2LE ' , headers = None , define = None ) :
2010-03-25 01:56:57 +03:00
''' check that a named charset is able to be used with iconv_open() for conversion
to a target charset
'''
msg = ' Checking if can we convert from %s to %s ' % ( charset , outcharset )
if define is None :
define = ' HAVE_CHARSET_ %s ' % charset . upper ( ) . replace ( ' - ' , ' _ ' )
return conf . CHECK_CODE ( '''
iconv_t cd = iconv_open ( " %s " , " %s " ) ;
2010-03-26 09:55:25 +03:00
if ( cd == 0 | | cd == ( iconv_t ) - 1 ) return - 1 ;
''' % (charset, outcharset),
2010-03-25 01:56:57 +03:00
define = define ,
execute = True ,
msg = msg ,
2010-03-26 09:55:25 +03:00
lib = ' iconv ' ,
2010-03-25 01:56:57 +03:00
headers = headers )
2010-03-26 05:12:50 +03:00
2010-03-28 14:00:51 +04:00
def find_config_dir ( conf ) :
''' find a directory to run tests in '''
2010-03-26 05:12:50 +03:00
k = 0
while k < 10000 :
dir = os . path . join ( conf . blddir , ' .conf_check_ %d ' % k )
try :
shutil . rmtree ( dir )
except OSError :
pass
try :
os . stat ( dir )
except :
break
k + = 1
try :
os . makedirs ( dir )
except :
conf . fatal ( ' cannot create a configuration test folder %r ' % dir )
try :
os . stat ( dir )
except :
conf . fatal ( ' cannot use the configuration test folder %r ' % dir )
2010-03-28 14:00:51 +04:00
return dir
2010-10-31 18:50:15 +03:00
@conf
def CHECK_SHLIB_INTRASINC_NAME_FLAGS ( conf , msg ) :
'''
check if the waf default flags for setting the name of lib
are ok
'''
snip = '''
int foo ( int v ) {
return v * 2 ;
}
'''
2015-11-12 02:27:31 +03:00
return conf . check ( features = ' c cshlib ' , vnum = " 1 " , fragment = snip , msg = msg , mandatory = False )
2010-10-31 18:50:15 +03:00
2010-12-10 23:16:28 +03:00
@conf
def CHECK_NEED_LC ( conf , msg ) :
''' check if we need -lc '''
dir = find_config_dir ( conf )
env = conf . env
bdir = os . path . join ( dir , ' testbuild2 ' )
if not os . path . exists ( bdir ) :
os . makedirs ( bdir )
subdir = os . path . join ( dir , " liblctest " )
os . makedirs ( subdir )
2015-06-26 21:48:43 +03:00
Utils . writef ( os . path . join ( subdir , ' liblc1.c ' ) , ' #include <stdio.h> \n int lib_func(void) { FILE *f = fopen( " foo " , " r " );} \n ' )
2010-12-10 23:16:28 +03:00
bld = Build . BuildContext ( )
bld . log = conf . log
bld . all_envs . update ( conf . all_envs )
bld . all_envs [ ' default ' ] = env
bld . lst_variants = bld . all_envs . keys ( )
bld . load_dirs ( dir , bdir )
bld . rescan ( bld . srcnode )
2015-10-03 23:29:15 +03:00
bld ( features = ' c cshlib ' ,
2010-12-10 23:16:28 +03:00
source = ' liblctest/liblc1.c ' ,
ldflags = conf . env [ ' EXTRA_LDFLAGS ' ] ,
target = ' liblc ' ,
name = ' liblc ' )
try :
bld . compile ( )
conf . check_message ( msg , ' ' , True )
return True
except :
conf . check_message ( msg , ' ' , False )
return False
2010-10-30 16:50:33 +04:00
@conf
def CHECK_SHLIB_W_PYTHON ( conf , msg ) :
''' check if we need -undefined dynamic_lookup '''
dir = find_config_dir ( conf )
snip = '''
#include <Python.h>
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
static PyObject * ldb_module = NULL ;
int foo ( int v ) {
extern char * * environ ;
environ [ 0 ] = 1 ;
ldb_module = PyImport_ImportModule ( " ldb " ) ;
return v * 2 ;
} '''
2015-11-12 02:27:31 +03:00
return conf . check ( features = ' c cshlib ' , uselib = ' PYEMBED ' , fragment = snip , msg = msg , mandatory = False )
2010-03-28 14:00:51 +04:00
# this one is quite complex, and should probably be broken up
# into several parts. I'd quite like to create a set of CHECK_COMPOUND()
# functions that make writing complex compound tests like this much easier
@conf
2010-12-08 03:26:32 +03:00
def CHECK_LIBRARY_SUPPORT ( conf , rpath = False , version_script = False , msg = None ) :
2010-03-28 14:00:51 +04:00
''' see if the platform supports building libraries '''
if msg is None :
if rpath :
msg = " rpath library support "
else :
msg = " building library support "
dir = find_config_dir ( conf )
2010-03-26 05:12:50 +03:00
bdir = os . path . join ( dir , ' testbuild ' )
if not os . path . exists ( bdir ) :
os . makedirs ( bdir )
env = conf . env
subdir = os . path . join ( dir , " libdir " )
os . makedirs ( subdir )
2015-06-26 21:48:43 +03:00
Utils . writef ( os . path . join ( subdir , ' lib1.c ' ) , ' int lib_func(void) { return 42; } \n ' )
2016-12-06 20:07:36 +03:00
Utils . writef ( os . path . join ( dir , ' main.c ' ) ,
' int lib_func(void); \n '
' int main(void) { return !(lib_func() == 42);} \n ' )
2010-03-26 05:12:50 +03:00
bld = Build . BuildContext ( )
bld . log = conf . log
bld . all_envs . update ( conf . all_envs )
bld . all_envs [ ' default ' ] = env
bld . lst_variants = bld . all_envs . keys ( )
bld . load_dirs ( dir , bdir )
bld . rescan ( bld . srcnode )
2010-12-08 03:26:32 +03:00
ldflags = [ ]
if version_script :
ldflags . append ( " -Wl,--version-script= %s /vscript " % bld . path . abspath ( ) )
2015-06-26 21:48:43 +03:00
Utils . writef ( os . path . join ( dir , ' vscript ' ) , ' TEST_1.0A2 { global: *; }; \n ' )
2010-12-08 03:26:32 +03:00
2015-10-03 23:29:15 +03:00
bld ( features = ' c cshlib ' ,
2010-03-26 05:12:50 +03:00
source = ' libdir/lib1.c ' ,
target = ' libdir/lib1 ' ,
2010-12-08 03:26:32 +03:00
ldflags = ldflags ,
2010-03-26 05:12:50 +03:00
name = ' lib1 ' )
2015-10-03 23:29:15 +03:00
o = bld ( features = ' c cprogram ' ,
2010-03-26 05:12:50 +03:00
source = ' main.c ' ,
target = ' prog1 ' ,
2010-03-28 10:24:05 +04:00
uselib_local = ' lib1 ' )
if rpath :
o . rpath = os . path . join ( bdir , ' default/libdir ' )
2010-03-26 05:12:50 +03:00
# compile the program
try :
bld . compile ( )
2010-03-26 05:20:05 +03:00
except :
2010-03-28 10:24:05 +04:00
conf . check_message ( msg , ' ' , False )
2010-03-26 05:20:05 +03:00
return False
2010-03-26 05:12:50 +03:00
# path for execution
lastprog = o . link_task . outputs [ 0 ] . abspath ( env )
2010-03-28 10:24:05 +04:00
if not rpath :
if ' LD_LIBRARY_PATH ' in os . environ :
old_ld_library_path = os . environ [ ' LD_LIBRARY_PATH ' ]
else :
old_ld_library_path = None
ADD_LD_LIBRARY_PATH ( os . path . join ( bdir , ' default/libdir ' ) )
2010-03-26 05:12:50 +03:00
# we need to run the program, try to get its result
2010-04-19 09:58:37 +04:00
args = conf . SAMBA_CROSS_ARGS ( msg = msg )
2010-03-26 05:12:50 +03:00
proc = Utils . pproc . Popen ( [ lastprog ] + args , stdout = Utils . pproc . PIPE , stderr = Utils . pproc . PIPE )
( out , err ) = proc . communicate ( )
w = conf . log . write
w ( str ( out ) )
w ( ' \n ' )
w ( str ( err ) )
w ( ' \n returncode %r \n ' % proc . returncode )
ret = ( proc . returncode == 0 )
2010-03-28 10:24:05 +04:00
if not rpath :
os . environ [ ' LD_LIBRARY_PATH ' ] = old_ld_library_path or ' '
conf . check_message ( msg , ' ' , ret )
2010-03-26 05:12:50 +03:00
return ret
2010-03-28 14:00:51 +04:00
@conf
def CHECK_PERL_MANPAGE ( conf , msg = None , section = None ) :
''' work out what extension perl uses for manpages '''
if msg is None :
if section :
msg = " perl man %s extension " % section
else :
msg = " perl manpage generation "
conf . check_message_1 ( msg )
dir = find_config_dir ( conf )
bdir = os . path . join ( dir , ' testbuild ' )
if not os . path . exists ( bdir ) :
os . makedirs ( bdir )
2015-06-26 21:48:43 +03:00
Utils . writef ( os . path . join ( bdir , ' Makefile.PL ' ) , """
2010-03-28 14:00:51 +04:00
use ExtUtils : : MakeMaker ;
WriteMakefile (
2012-02-09 16:08:31 +04:00
' NAME ' = > ' WafTest ' ,
2010-03-28 14:00:51 +04:00
' EXE_FILES ' = > [ ' WafTest ' ]
) ;
""" )
back = os . path . abspath ( ' . ' )
os . chdir ( bdir )
proc = Utils . pproc . Popen ( [ ' perl ' , ' Makefile.PL ' ] ,
stdout = Utils . pproc . PIPE ,
stderr = Utils . pproc . PIPE )
( out , err ) = proc . communicate ( )
os . chdir ( back )
ret = ( proc . returncode == 0 )
if not ret :
conf . check_message_2 ( ' not found ' , color = ' YELLOW ' )
return
if section :
2015-06-26 21:48:43 +03:00
man = Utils . readf ( os . path . join ( bdir , ' Makefile ' ) )
2010-03-28 14:00:51 +04:00
m = re . search ( ' MAN %s EXT \ s+= \ s+( \ w+) ' % section , man )
if not m :
conf . check_message_2 ( ' not found ' , color = ' YELLOW ' )
return
ext = m . group ( 1 )
conf . check_message_2 ( ext )
return ext
conf . check_message_2 ( ' ok ' )
return True
2010-04-20 17:17:32 +04:00
@conf
2010-06-24 10:02:43 +04:00
def CHECK_COMMAND ( conf , cmd , msg = None , define = None , on_target = True , boolean = False ) :
2010-04-21 09:15:55 +04:00
''' run a command and return result '''
2010-04-20 17:17:32 +04:00
if msg is None :
2010-04-21 09:15:55 +04:00
msg = ' Checking %s ' % ' ' . join ( cmd )
2010-04-20 17:17:32 +04:00
conf . COMPOUND_START ( msg )
2010-04-21 09:15:55 +04:00
cmd = cmd [ : ]
if on_target :
cmd . extend ( conf . SAMBA_CROSS_ARGS ( msg = msg ) )
try :
ret = Utils . cmd_output ( cmd )
except :
conf . COMPOUND_END ( False )
return False
2010-06-24 10:02:43 +04:00
if boolean :
conf . COMPOUND_END ( ' ok ' )
if define :
conf . DEFINE ( define , ' 1 ' )
else :
ret = ret . strip ( )
conf . COMPOUND_END ( ret )
if define :
conf . DEFINE ( define , ret , quote = True )
2010-04-20 17:17:32 +04:00
return ret
2010-04-21 09:15:55 +04:00
@conf
def CHECK_UNAME ( conf ) :
''' setup SYSTEM_UNAME_* defines '''
ret = True
for v in " sysname machine release version " . split ( ) :
if not conf . CHECK_CODE ( '''
2016-12-06 20:07:43 +03:00
int printf ( const char * format , . . . ) ;
2010-04-21 09:15:55 +04:00
struct utsname n ;
2010-05-02 18:12:14 +04:00
if ( uname ( & n ) == - 1 ) return - 1 ;
2010-04-21 09:15:55 +04:00
printf ( " %% s " , n . % s ) ;
''' % v,
define = ' SYSTEM_UNAME_ %s ' % v . upper ( ) ,
execute = True ,
define_ret = True ,
quote = True ,
headers = ' sys/utsname.h ' ,
local_include = False ,
msg = " Checking uname %s type " % v ) :
ret = False
return ret
2010-05-05 17:16:26 +04:00
@conf
def CHECK_INLINE ( conf ) :
''' check for the right value for inline '''
conf . COMPOUND_START ( ' Checking for inline ' )
for i in [ ' inline ' , ' __inline__ ' , ' __inline ' ] :
ret = conf . CHECK_CODE ( '''
typedef int foo_t ;
static % s foo_t static_foo ( ) { return 0 ; }
% s foo_t foo ( ) { return 0 ; } ''' % (i, i),
define = ' INLINE_MACRO ' ,
addmain = False ,
link = False )
if ret :
if i != ' inline ' :
conf . DEFINE ( ' inline ' , i , quote = False )
break
if not ret :
conf . COMPOUND_END ( ret )
else :
conf . COMPOUND_END ( i )
return ret
2010-06-24 10:02:43 +04:00
@conf
def CHECK_XSLTPROC_MANPAGES ( conf ) :
''' check if xsltproc can run with the given stylesheets '''
2010-05-05 17:16:26 +04:00
2010-06-24 10:02:43 +04:00
if not conf . CONFIG_SET ( ' XSLTPROC ' ) :
conf . find_program ( ' xsltproc ' , var = ' XSLTPROC ' )
if not conf . CONFIG_SET ( ' XSLTPROC ' ) :
return False
2010-08-22 07:02:00 +04:00
s = ' http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl '
conf . CHECK_COMMAND ( ' %s --nonet %s 2> /dev/null ' % ( conf . env . XSLTPROC , s ) ,
msg = ' Checking for stylesheet %s ' % s ,
define = ' XSLTPROC_MANPAGES ' , on_target = False ,
boolean = True )
2013-05-06 02:05:37 +04:00
if not conf . CONFIG_SET ( ' XSLTPROC_MANPAGES ' ) :
print " A local copy of the docbook.xsl wasn ' t found on your system " \
" consider installing package like docbook-xsl "
wafsamba: fix ordering problems with lib-provided and internal RPATHs
When a library or system (like cups) provides an RPATH,
e.g. with -Wl,-R or -Wl,-rpath, this was added by waf
to the LINKFLAGS, wich was later prepended to our RPATH.
But if the path by chance contains an older version of
one of our internal libraries like talloc, this would lead
to linking the too old talloc into our binaries.
This has been observed on, e.g., FreeBSD, but it is a general
problem.
This patch fixes the problem by specially parsing the RPATH
linker options from the pkg-config(, cups-config, ....) output
and putting the paths into the RPATH_<lib> container, which
is then later correctly appended to our internal RPATH.
This is a better fix than commit 64f5e24100a764ec198cab9a8d2c43fa86e7027c
as it touches wafsamba only. 64f5e24100a764ec198cab9a8d2c43fa86e7027c
is already in waf 1.5 upstream, but has some possible bugs,
e.g. it doesn't handle -Wl,-R, (with ',' at the end)
or some combinations where the path is given via an additional
-Wl,/path argument.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10548
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Michael Adam <obnox@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
2014-12-18 20:09:15 +03:00
2014-12-18 23:36:07 +03:00
#
# Determine the standard libpath for the used compiler,
# so we can later use that to filter out these standard
# library paths when some tools like cups-config or
# python-config report standard lib paths with their
# ldflags (-L...)
#
@conf
def CHECK_STANDARD_LIBPATH ( conf ) :
# at least gcc and clang support this:
try :
cmd = conf . env . CC + [ ' -print-search-dirs ' ]
out = Utils . cmd_output ( cmd ) . split ( ' \n ' )
except ValueError :
# option not supported by compiler - use a standard list of directories
dirlist = [ ' /usr/lib ' , ' /usr/lib64 ' ]
except :
raise Utils . WafError ( ' Unexpected error running " %s " ' % ( cmd ) )
else :
dirlist = [ ]
for line in out :
line = line . strip ( )
if line . startswith ( " libraries: = " ) :
dirliststr = line [ len ( " libraries: = " ) : ]
dirlist = [ os . path . normpath ( x ) for x in dirliststr . split ( ' : ' ) ]
break
conf . env . STANDARD_LIBPATH = dirlist