s4-waf: added auto-detection of perl manpage extensions
[nivanova/samba-autobuild/.git] / buildtools / wafsamba / samba_conftests.py
1 # a set of config tests that use the samba_autoconf functions
2 # to test for commonly needed configuration options
3
4 import os, Build, shutil, Utils, re
5 from Configure import conf
6 from samba_utils import *
7
8 @conf
9 def CHECK_ICONV(conf, define='HAVE_NATIVE_ICONV'):
10     '''check if the iconv library is installed
11        optionally pass a define'''
12     if conf.CHECK_FUNCS_IN('iconv_open', 'iconv', checklibc=True, headers='iconv.h'):
13         conf.DEFINE(define, 1)
14         return True
15     return False
16
17
18 @conf
19 def CHECK_LARGEFILE(conf, define='HAVE_LARGEFILE'):
20     '''see what we need for largefile support'''
21     if conf.CHECK_CODE('return !(sizeof(off_t) >= 8)',
22                        define,
23                        execute=True,
24                        msg='Checking for large file support'):
25         return True
26     if conf.CHECK_CODE('return !(sizeof(off_t) >= 8)',
27                        define,
28                        execute=True,
29                        cflags='-D_FILE_OFFSET_BITS=64',
30                        msg='Checking for -D_FILE_OFFSET_BITS=64'):
31         conf.DEFINE('_FILE_OFFSET_BITS', 64)
32         return True
33     return False
34
35
36 @conf
37 def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None):
38     '''verify that a C prototype matches the one on the current system'''
39     if not conf.CHECK_DECLS(function, headers=headers):
40         return False
41     return conf.CHECK_CODE('%s; void *_x = (void *)%s' % (prototype, function),
42                            define=define,
43                            local_include=False,
44                            headers=headers,
45                            msg='Checking C prototype for %s' % function)
46
47
48 @conf
49 def CHECK_CHARSET_EXISTS(conf, charset, outcharset='UCS-2LE', headers=None, define=None):
50     '''check that a named charset is able to be used with iconv_open() for conversion
51     to a target charset
52     '''
53     msg = 'Checking if can we convert from %s to %s' % (charset, outcharset)
54     if define is None:
55         define = 'HAVE_CHARSET_%s' % charset.upper().replace('-','_')
56     return conf.CHECK_CODE('''
57                            iconv_t cd = iconv_open("%s", "%s");
58                            if (cd == 0 || cd == (iconv_t)-1) return -1;
59                            ''' % (charset, outcharset),
60                            define=define,
61                            execute=True,
62                            msg=msg,
63                            lib='iconv',
64                            headers=headers)
65
66 def find_config_dir(conf):
67     '''find a directory to run tests in'''
68     k = 0
69     while k < 10000:
70         dir = os.path.join(conf.blddir, '.conf_check_%d' % k)
71         try:
72             shutil.rmtree(dir)
73         except OSError:
74             pass
75         try:
76             os.stat(dir)
77         except:
78             break
79         k += 1
80
81     try:
82         os.makedirs(dir)
83     except:
84         conf.fatal('cannot create a configuration test folder %r' % dir)
85
86     try:
87         os.stat(dir)
88     except:
89         conf.fatal('cannot use the configuration test folder %r' % dir)
90     return dir
91
92
93 # this one is quite complex, and should probably be broken up
94 # into several parts. I'd quite like to create a set of CHECK_COMPOUND()
95 # functions that make writing complex compound tests like this much easier
96 @conf
97 def CHECK_LIBRARY_SUPPORT(conf, rpath=False, msg=None):
98     '''see if the platform supports building libraries'''
99
100     if msg is None:
101         if rpath:
102             msg = "rpath library support"
103         else:
104             msg = "building library support"
105
106     dir = find_config_dir(conf)
107
108     bdir = os.path.join(dir, 'testbuild')
109     if not os.path.exists(bdir):
110         os.makedirs(bdir)
111
112     env = conf.env
113
114     subdir = os.path.join(dir, "libdir")
115
116     os.makedirs(subdir)
117
118     dest = open(os.path.join(subdir, 'lib1.c'), 'w')
119     dest.write('int lib_func(void) { return 42; }\n')
120     dest.close()
121
122     dest = open(os.path.join(dir, 'main.c'), 'w')
123     dest.write('int main(void) {return !(lib_func() == 42);}\n')
124     dest.close()
125
126     bld = Build.BuildContext()
127     bld.log = conf.log
128     bld.all_envs.update(conf.all_envs)
129     bld.all_envs['default'] = env
130     bld.lst_variants = bld.all_envs.keys()
131     bld.load_dirs(dir, bdir)
132
133     bld.rescan(bld.srcnode)
134
135     bld(features='cc cshlib',
136         source='libdir/lib1.c',
137         target='libdir/lib1',
138         name='lib1')
139
140     o = bld(features='cc cprogram',
141             source='main.c',
142             target='prog1',
143             uselib_local='lib1')
144
145     if rpath:
146         o.rpath=os.path.join(bdir, 'default/libdir')
147
148     # compile the program
149     try:
150         bld.compile()
151     except:
152         conf.check_message(msg, '', False)
153         return False
154
155     # path for execution
156     lastprog = o.link_task.outputs[0].abspath(env)
157
158     if not rpath:
159         if 'LD_LIBRARY_PATH' in os.environ:
160             old_ld_library_path = os.environ['LD_LIBRARY_PATH']
161         else:
162             old_ld_library_path = None
163         ADD_LD_LIBRARY_PATH(os.path.join(bdir, 'default/libdir'))
164
165     # we need to run the program, try to get its result
166     args = []
167     proc = Utils.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE)
168     (out, err) = proc.communicate()
169     w = conf.log.write
170     w(str(out))
171     w('\n')
172     w(str(err))
173     w('\nreturncode %r\n' % proc.returncode)
174     ret = (proc.returncode == 0)
175
176     if not rpath:
177         os.environ['LD_LIBRARY_PATH'] = old_ld_library_path or ''
178
179     conf.check_message(msg, '', ret)
180     return ret
181
182
183
184 @conf
185 def CHECK_PERL_MANPAGE(conf, msg=None, section=None):
186     '''work out what extension perl uses for manpages'''
187
188     if msg is None:
189         if section:
190             msg = "perl man%s extension" % section
191         else:
192             msg = "perl manpage generation"
193
194     conf.check_message_1(msg)
195
196     dir = find_config_dir(conf)
197
198     bdir = os.path.join(dir, 'testbuild')
199     if not os.path.exists(bdir):
200         os.makedirs(bdir)
201
202     dest = open(os.path.join(bdir, 'Makefile.PL'), 'w')
203     dest.write("""
204 use ExtUtils::MakeMaker;
205 WriteMakefile(
206     'NAME'      => 'WafTest',
207     'EXE_FILES' => [ 'WafTest' ]
208 );
209 """)
210     dest.close()
211     back = os.path.abspath('.')
212     os.chdir(bdir)
213     proc = Utils.pproc.Popen(['perl', 'Makefile.PL'],
214                              stdout=Utils.pproc.PIPE,
215                              stderr=Utils.pproc.PIPE)
216     (out, err) = proc.communicate()
217     os.chdir(back)
218
219     ret = (proc.returncode == 0)
220     if not ret:
221         conf.check_message_2('not found', color='YELLOW')
222         return
223
224     if section:
225         f = open(os.path.join(bdir,'Makefile'), 'r')
226         man = f.read()
227         f.close()
228         m = re.search('MAN%sEXT\s+=\s+(\w+)' % section, man)
229         if not m:
230             conf.check_message_2('not found', color='YELLOW')
231             return
232         ext = m.group(1)
233         conf.check_message_2(ext)
234         return ext
235
236     conf.check_message_2('ok')
237     return True