build: check if the manpages stylesheet is available locally
[metze/samba/wip.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, msg=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     if not msg:
42         msg = 'Checking C prototype for %s' % function
43     return conf.CHECK_CODE('%s; void *_x = (void *)%s' % (prototype, function),
44                            define=define,
45                            local_include=False,
46                            headers=headers,
47                            link=False,
48                            execute=False,
49                            msg=msg)
50
51
52 @conf
53 def CHECK_CHARSET_EXISTS(conf, charset, outcharset='UCS-2LE', headers=None, define=None):
54     '''check that a named charset is able to be used with iconv_open() for conversion
55     to a target charset
56     '''
57     msg = 'Checking if can we convert from %s to %s' % (charset, outcharset)
58     if define is None:
59         define = 'HAVE_CHARSET_%s' % charset.upper().replace('-','_')
60     return conf.CHECK_CODE('''
61                            iconv_t cd = iconv_open("%s", "%s");
62                            if (cd == 0 || cd == (iconv_t)-1) return -1;
63                            ''' % (charset, outcharset),
64                            define=define,
65                            execute=True,
66                            msg=msg,
67                            lib='iconv',
68                            headers=headers)
69
70 def find_config_dir(conf):
71     '''find a directory to run tests in'''
72     k = 0
73     while k < 10000:
74         dir = os.path.join(conf.blddir, '.conf_check_%d' % k)
75         try:
76             shutil.rmtree(dir)
77         except OSError:
78             pass
79         try:
80             os.stat(dir)
81         except:
82             break
83         k += 1
84
85     try:
86         os.makedirs(dir)
87     except:
88         conf.fatal('cannot create a configuration test folder %r' % dir)
89
90     try:
91         os.stat(dir)
92     except:
93         conf.fatal('cannot use the configuration test folder %r' % dir)
94     return dir
95
96
97 # this one is quite complex, and should probably be broken up
98 # into several parts. I'd quite like to create a set of CHECK_COMPOUND()
99 # functions that make writing complex compound tests like this much easier
100 @conf
101 def CHECK_LIBRARY_SUPPORT(conf, rpath=False, msg=None):
102     '''see if the platform supports building libraries'''
103
104     if msg is None:
105         if rpath:
106             msg = "rpath library support"
107         else:
108             msg = "building library support"
109
110     dir = find_config_dir(conf)
111
112     bdir = os.path.join(dir, 'testbuild')
113     if not os.path.exists(bdir):
114         os.makedirs(bdir)
115
116     env = conf.env
117
118     subdir = os.path.join(dir, "libdir")
119
120     os.makedirs(subdir)
121
122     dest = open(os.path.join(subdir, 'lib1.c'), 'w')
123     dest.write('int lib_func(void) { return 42; }\n')
124     dest.close()
125
126     dest = open(os.path.join(dir, 'main.c'), 'w')
127     dest.write('int main(void) {return !(lib_func() == 42);}\n')
128     dest.close()
129
130     bld = Build.BuildContext()
131     bld.log = conf.log
132     bld.all_envs.update(conf.all_envs)
133     bld.all_envs['default'] = env
134     bld.lst_variants = bld.all_envs.keys()
135     bld.load_dirs(dir, bdir)
136
137     bld.rescan(bld.srcnode)
138
139     bld(features='cc cshlib',
140         source='libdir/lib1.c',
141         target='libdir/lib1',
142         name='lib1')
143
144     o = bld(features='cc cprogram',
145             source='main.c',
146             target='prog1',
147             uselib_local='lib1')
148
149     if rpath:
150         o.rpath=os.path.join(bdir, 'default/libdir')
151
152     # compile the program
153     try:
154         bld.compile()
155     except:
156         conf.check_message(msg, '', False)
157         return False
158
159     # path for execution
160     lastprog = o.link_task.outputs[0].abspath(env)
161
162     if not rpath:
163         if 'LD_LIBRARY_PATH' in os.environ:
164             old_ld_library_path = os.environ['LD_LIBRARY_PATH']
165         else:
166             old_ld_library_path = None
167         ADD_LD_LIBRARY_PATH(os.path.join(bdir, 'default/libdir'))
168
169     # we need to run the program, try to get its result
170     args = conf.SAMBA_CROSS_ARGS(msg=msg)
171     proc = Utils.pproc.Popen([lastprog] + args, stdout=Utils.pproc.PIPE, stderr=Utils.pproc.PIPE)
172     (out, err) = proc.communicate()
173     w = conf.log.write
174     w(str(out))
175     w('\n')
176     w(str(err))
177     w('\nreturncode %r\n' % proc.returncode)
178     ret = (proc.returncode == 0)
179
180     if not rpath:
181         os.environ['LD_LIBRARY_PATH'] = old_ld_library_path or ''
182
183     conf.check_message(msg, '', ret)
184     return ret
185
186
187
188 @conf
189 def CHECK_PERL_MANPAGE(conf, msg=None, section=None):
190     '''work out what extension perl uses for manpages'''
191
192     if msg is None:
193         if section:
194             msg = "perl man%s extension" % section
195         else:
196             msg = "perl manpage generation"
197
198     conf.check_message_1(msg)
199
200     dir = find_config_dir(conf)
201
202     bdir = os.path.join(dir, 'testbuild')
203     if not os.path.exists(bdir):
204         os.makedirs(bdir)
205
206     dest = open(os.path.join(bdir, 'Makefile.PL'), 'w')
207     dest.write("""
208 use ExtUtils::MakeMaker;
209 WriteMakefile(
210     'NAME'      => 'WafTest',
211     'EXE_FILES' => [ 'WafTest' ]
212 );
213 """)
214     dest.close()
215     back = os.path.abspath('.')
216     os.chdir(bdir)
217     proc = Utils.pproc.Popen(['perl', 'Makefile.PL'],
218                              stdout=Utils.pproc.PIPE,
219                              stderr=Utils.pproc.PIPE)
220     (out, err) = proc.communicate()
221     os.chdir(back)
222
223     ret = (proc.returncode == 0)
224     if not ret:
225         conf.check_message_2('not found', color='YELLOW')
226         return
227
228     if section:
229         f = open(os.path.join(bdir,'Makefile'), 'r')
230         man = f.read()
231         f.close()
232         m = re.search('MAN%sEXT\s+=\s+(\w+)' % section, man)
233         if not m:
234             conf.check_message_2('not found', color='YELLOW')
235             return
236         ext = m.group(1)
237         conf.check_message_2(ext)
238         return ext
239
240     conf.check_message_2('ok')
241     return True
242
243
244 @conf
245 def CHECK_COMMAND(conf, cmd, msg=None, define=None, on_target=True, boolean=False):
246     '''run a command and return result'''
247     if msg is None:
248         msg = 'Checking %s' % ' '.join(cmd)
249     conf.COMPOUND_START(msg)
250     cmd = cmd[:]
251     if on_target:
252         cmd.extend(conf.SAMBA_CROSS_ARGS(msg=msg))
253     try:
254         ret = Utils.cmd_output(cmd)
255     except:
256         conf.COMPOUND_END(False)
257         return False
258     if boolean:
259         conf.COMPOUND_END('ok')
260         if define:
261             conf.DEFINE(define, '1')
262     else:
263         ret = ret.strip()
264         conf.COMPOUND_END(ret)
265         if define:
266             conf.DEFINE(define, ret, quote=True)
267     return ret
268
269
270 @conf
271 def CHECK_UNAME(conf):
272     '''setup SYSTEM_UNAME_* defines'''
273     ret = True
274     for v in "sysname machine release version".split():
275         if not conf.CHECK_CODE('''
276                                struct utsname n;
277                                if (uname(&n) == -1) return -1;
278                                printf("%%s", n.%s);
279                                ''' % v,
280                                define='SYSTEM_UNAME_%s' % v.upper(),
281                                execute=True,
282                                define_ret=True,
283                                quote=True,
284                                headers='sys/utsname.h',
285                                local_include=False,
286                                msg="Checking uname %s type" % v):
287             ret = False
288     return ret
289
290 @conf
291 def CHECK_INLINE(conf):
292     '''check for the right value for inline'''
293     conf.COMPOUND_START('Checking for inline')
294     for i in ['inline', '__inline__', '__inline']:
295         ret = conf.CHECK_CODE('''
296         typedef int foo_t;
297         static %s foo_t static_foo () {return 0; }
298         %s foo_t foo () {return 0; }''' % (i, i),
299                               define='INLINE_MACRO',
300                               addmain=False,
301                               link=False)
302         if ret:
303             if i != 'inline':
304                 conf.DEFINE('inline', i, quote=False)
305             break
306     if not ret:
307         conf.COMPOUND_END(ret)
308     else:
309         conf.COMPOUND_END(i)
310     return ret
311
312 @conf
313 def CHECK_XSLTPROC_MANPAGES(conf):
314     '''check if xsltproc can run with the given stylesheets'''
315
316     stylesheets='http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
317
318     if not conf.CONFIG_SET('XSLTPROC'):
319         conf.find_program('xsltproc', var='XSLTPROC')
320     if not conf.CONFIG_SET('XSLTPROC'):
321         return False
322
323     for s in TO_LIST(stylesheets):
324         if not conf.CONFIG_SET('XSLTPROC_%s' % s):
325             ret = conf.CHECK_COMMAND('%s --nonet %s 2> /dev/null' % (conf.env.XSLTPROC, s),
326                                      msg='Checking for stylesheet %s' % s,
327                                      define=None, on_target=False,
328                                      boolean=True)
329             if not ret:
330                 return False
331             conf.env['XSLTPROC_%s' % s] = True
332     conf.env['XSLTPROC_MANPAGES'] = True
333     return True