207d7320b95445b250c72a4fc75087025b01372a
[amitay/samba.git] / buildtools / wafsamba / samba_autoconf.py
1 # a waf tool to add autoconf-like macros to the configure section
2
3 import Build, os, sys, Options, preproc, Logs
4 import string
5 from Configure import conf
6 from samba_utils import *
7 import samba_cross
8
9 missing_headers = set()
10
11 ####################################################
12 # some autoconf like helpers, to make the transition
13 # to waf a bit easier for those used to autoconf
14 # m4 files
15
16 @runonce
17 @conf
18 def DEFINE(conf, d, v, add_to_cflags=False, quote=False):
19     '''define a config option'''
20     conf.define(d, v, quote=quote)
21     if add_to_cflags:
22         conf.env.append_value('CCDEFINES', d + '=' + str(v))
23
24 def hlist_to_string(conf, headers=None):
25     '''convert a headers list to a set of #include lines'''
26     hdrs=''
27     hlist = conf.env.hlist
28     if headers:
29         hlist = hlist[:]
30         hlist.extend(TO_LIST(headers))
31     for h in hlist:
32         hdrs += '#include <%s>\n' % h
33     return hdrs
34
35
36 @conf
37 def COMPOUND_START(conf, msg):
38     '''start a compound test'''
39     def null_check_message_1(self,*k,**kw):
40         return
41     def null_check_message_2(self,*k,**kw):
42         return
43
44     v = getattr(conf.env, 'in_compound', [])
45     if v != [] and v != 0:
46         conf.env.in_compound = v + 1
47         return
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
54
55
56 @conf
57 def COMPOUND_END(conf, result):
58     '''start a compound test'''
59     conf.env.in_compound -= 1
60     if conf.env.in_compound != 0:
61         return
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
65     if result == True:
66         p('ok ')
67     elif result == False:
68         p('not found', 'YELLOW')
69     else:
70         p(result)
71
72
73 @feature('nolink')
74 def nolink(self):
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'''
78     pass
79
80
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:
84         return False
85     d = h.upper().replace('/', '_')
86     d = d.replace('.', '_')
87     d = d.replace('-', '_')
88     d = 'HAVE_%s' % d
89     if CONFIG_SET(conf, d):
90         if add_headers:
91             if not h in conf.env.hlist:
92                 conf.env.hlist.append(h)
93         return True
94
95     (ccflags, ldflags) = library_flags(conf, lib)
96
97     hdrs = hlist_to_string(conf, headers=h)
98     ret = conf.check(fragment='%s\nint main(void) { return 0; }' % hdrs,
99                      type='nolink',
100                      execute=0,
101                      ccflags=ccflags,
102                      msg="Checking for header %s" % h)
103     if not ret:
104         missing_headers.add(h)
105         return False
106
107     conf.DEFINE(d, 1)
108     if add_headers and not h in conf.env.hlist:
109         conf.env.hlist.append(h)
110     return ret
111
112
113 @conf
114 def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None):
115     '''check for a list of headers
116
117     when together==True, then the headers accumulate within this test.
118     This is useful for interdependent headers
119     '''
120     ret = True
121     if not add_headers and together:
122         saved_hlist = conf.env.hlist[:]
123         set_add_headers = True
124     else:
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):
128             ret = False
129     if not add_headers and together:
130         conf.env.hlist = saved_hlist
131     return ret
132
133
134 def header_list(conf, headers=None, lib=None):
135     '''form a list of headers which exist, as a string'''
136     hlist=[]
137     if headers is not None:
138         for h in TO_LIST(headers):
139             if CHECK_HEADER(conf, h, add_headers=False, lib=lib):
140                 hlist.append(h)
141     return hlist_to_string(conf, headers=hlist)
142
143
144 @conf
145 def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
146     '''check for a single type'''
147     if define is None:
148         define = 'HAVE_' + t.upper().replace(' ', '_')
149     if msg is None:
150         msg='Checking for %s' % t
151     ret = CHECK_CODE(conf, '%s _x' % t,
152                      define,
153                      execute=False,
154                      headers=headers,
155                      local_include=False,
156                      msg=msg,
157                      lib=lib,
158                      link=False)
159     if not ret and alternate:
160         conf.DEFINE(t, alternate)
161     return ret
162
163
164 @conf
165 def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None):
166     '''check for a list of types'''
167     ret = True
168     for t in TO_LIST(list):
169         if not CHECK_TYPE(conf, t, headers=headers,
170                           define=define, alternate=alternate, lib=lib):
171             ret = False
172     return ret
173
174
175 @conf
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)
179
180
181 @conf
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)'''
185     if define is None:
186         define = 'HAVE_%s' % v.upper()
187
188     if msg is None:
189         msg="Checking for variable %s" % v
190
191     return CHECK_CODE(conf,
192                       # we need to make sure the compiler doesn't
193                       # optimize it out...
194                       '''
195                       #ifndef %s
196                       void *_x; _x=(void *)&%s; return (int)_x;
197                       #endif
198                       return 0
199                       ''' % (v, v),
200                       execute=False,
201                       link=False,
202                       msg=msg,
203                       local_include=False,
204                       lib=lib,
205                       headers=headers,
206                       define=define,
207                       always=always)
208
209
210 @conf
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
213        of define
214
215        When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx
216        '''
217     ret = True
218     for v in TO_LIST(vars):
219         if not reverse:
220             define='HAVE_DECL_%s' % v.upper()
221         else:
222             define='HAVE_%s_DECL' % v.upper()
223         if not CHECK_VARIABLE(conf, v,
224                               define=define,
225                               headers=headers,
226                               msg='Checking for declaration of %s' % v,
227                               always=always):
228             ret = False
229     return ret
230
231
232 def CHECK_FUNC(conf, f, link=True, lib=None, headers=None):
233     '''check for a function'''
234     define='HAVE_%s' % f.upper()
235
236     ret = False
237
238     conf.COMPOUND_START('Checking for %s' % f)
239
240     if link is None or link == True:
241         ret = CHECK_CODE(conf,
242                          # this is based on the autoconf strategy
243                          '''
244                          #define %s __fake__%s
245                          #ifdef HAVE_LIMITS_H
246                          # include <limits.h>
247                          #else
248                          # include <assert.h>
249                          #endif
250                          #undef %s
251                          #if defined __stub_%s || defined __stub___%s
252                          #error "bad glibc stub"
253                          #endif
254                          extern char %s();
255                          int main() { return %s(); }
256                          ''' % (f, f, f, f, f, f, f),
257                          execute=False,
258                          link=True,
259                          addmain=False,
260                          add_headers=False,
261                          define=define,
262                          local_include=False,
263                          lib=lib,
264                          headers=headers,
265                          msg='Checking for %s' % f)
266
267         if not ret:
268             ret = CHECK_CODE(conf,
269                              # it might be a macro
270                              # we need to make sure the compiler doesn't
271                              # optimize it out...
272                              'void *__x = (void *)%s; return (int)__x' % f,
273                              execute=False,
274                              link=True,
275                              addmain=True,
276                              add_headers=True,
277                              define=define,
278                              local_include=False,
279                              lib=lib,
280                              headers=headers,
281                              msg='Checking for macro %s' % f)
282
283     if not ret and (link is None or link == False):
284         ret = CHECK_VARIABLE(conf, f,
285                              define=define,
286                              headers=headers,
287                              msg='Checking for declaration of %s' % f)
288     conf.COMPOUND_END(ret)
289     return ret
290
291
292 @conf
293 def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None):
294     '''check for a list of functions'''
295     ret = True
296     for f in TO_LIST(list):
297         if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers):
298             ret = False
299     return ret
300
301
302 @conf
303 def CHECK_SIZEOF(conf, vars, headers=None, define=None):
304     '''check the size of a type'''
305     ret = True
306     for v in TO_LIST(vars):
307         v_define = define
308         if v_define is None:
309             v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_')
310         if not CHECK_CODE(conf,
311                           'printf("%%u", (unsigned)sizeof(%s))' % v,
312                           define=v_define,
313                           execute=True,
314                           define_ret=True,
315                           quote=False,
316                           headers=headers,
317                           local_include=False,
318                           msg="Checking size of %s" % v):
319             ret = False
320     return ret
321
322
323
324 @conf
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,
331                on_target=True):
332     '''check if some code compiles and/or runs'''
333
334     if CONFIG_SET(conf, define):
335         return True
336
337     if headers is not None:
338         CHECK_HEADERS(conf, headers=headers, lib=lib)
339
340     if add_headers:
341         hdrs = header_list(conf, headers=headers, lib=lib)
342     else:
343         hdrs = ''
344     if execute:
345         execute = 1
346     else:
347         execute = 0
348
349     defs = conf.get_config_header()
350
351     if addmain:
352         fragment='%s\n%s\n int main(void) { %s; return 0; }\n' % (defs, hdrs, code)
353     else:
354         fragment='%s\n%s\n%s\n' % (defs, hdrs, code)
355
356     if msg is None:
357         msg="Checking for %s" % define
358
359     cflags = TO_LIST(cflags)
360
361     if local_include:
362         cflags.append('-I%s' % conf.curdir)
363
364     if not link:
365         type='nolink'
366     else:
367         type='cprogram'
368
369     uselib = TO_LIST(lib)
370
371     (ccflags, ldflags) = library_flags(conf, uselib)
372
373     cflags.extend(ccflags)
374
375     if on_target:
376         exec_args = conf.SAMBA_CROSS_ARGS(msg=msg)
377     else:
378         exec_args = []
379
380     conf.COMPOUND_START(msg)
381
382     ret = conf.check(fragment=fragment,
383                      execute=execute,
384                      define_name = define,
385                      mandatory = mandatory,
386                      ccflags=cflags,
387                      ldflags=ldflags,
388                      includes=includes,
389                      uselib=uselib,
390                      type=type,
391                      msg=msg,
392                      quote=quote,
393                      exec_args=exec_args,
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?
398         ret = True
399     if ret:
400         if not define_ret:
401             conf.DEFINE(define, 1)
402             conf.COMPOUND_END(True)
403         else:
404             conf.COMPOUND_END(conf.env[define])
405         return True
406     if always:
407         conf.DEFINE(define, 0)
408     conf.COMPOUND_END(False)
409     return False
410
411
412
413 @conf
414 def CHECK_STRUCTURE_MEMBER(conf, structname, member,
415                            always=False, define=None, headers=None):
416     '''check for a structure member'''
417     if define is None:
418         define = 'HAVE_%s' % member.upper()
419     return CHECK_CODE(conf,
420                       '%s s; void *_x; _x=(void *)&s.%s' % (structname, member),
421                       define,
422                       execute=False,
423                       link=False,
424                       always=always,
425                       headers=headers,
426                       local_include=False,
427                       msg="Checking for member %s in %s" % (member, structname))
428
429
430 @conf
431 def CHECK_CFLAGS(conf, cflags):
432     '''check if the given cflags are accepted by the compiler
433     '''
434     return conf.check(fragment='int main(void) { return 0; }\n',
435                       execute=0,
436                       type='nolink',
437                       ccflags=cflags,
438                       msg="Checking compiler accepts %s" % cflags)
439
440 @conf
441 def CHECK_LDFLAGS(conf, ldflags):
442     '''check if the given ldflags are accepted by the linker
443     '''
444     return conf.check(fragment='int main(void) { return 0; }\n',
445                       execute=0,
446                       ldflags=ldflags,
447                       msg="Checking linker accepts %s" % ldflags)
448
449
450 @conf
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]
455     else:
456         return None
457
458 @conf
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
464
465
466 def library_flags(self, libs):
467     '''work out flags from pkg_config'''
468     ccflags = []
469     ldflags = []
470     for lib in TO_LIST(libs):
471         inc_path = getattr(self.env, 'CPPPATH_%s' % lib.upper(), [])
472         lib_path = getattr(self.env, 'LIBPATH_%s' % lib.upper(), [])
473         ccflags.extend(['-I%s' % i for i in inc_path])
474         ldflags.extend(['-L%s' % l for l in lib_path])
475         extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
476         extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
477         ccflags.extend(extra_ccflags)
478         ldflags.extend(extra_ldflags)
479     if 'EXTRA_LDFLAGS' in self.env:
480         ldflags.extend(self.env['EXTRA_LDFLAGS'])
481
482     ccflags = unique_list(ccflags)
483     ldflags = unique_list(ldflags)
484     return (ccflags, ldflags)
485
486
487 @conf
488 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
489     '''check if a set of libraries exist as system libraries
490
491     returns the sublist of libs that do exist as a syslib or []
492     '''
493
494     fragment= '''
495 int foo()
496 {
497     int v = 2;
498     return v*2;
499 }
500 '''
501     ret = []
502     liblist  = TO_LIST(libs)
503     for lib in liblist[:]:
504         if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
505             ret.append(lib)
506             continue
507
508         (ccflags, ldflags) = library_flags(conf, lib)
509         if shlib:
510             res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
511         else:
512             res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
513
514         if not res:
515             if mandatory:
516                 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
517                 sys.exit(1)
518             if empty_decl:
519                 # if it isn't a mandatory library, then remove it from dependency lists
520                 if set_target:
521                     SET_TARGET_TYPE(conf, lib, 'EMPTY')
522         else:
523             conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
524             conf.env['LIB_' + lib.upper()] = lib
525             if set_target:
526                 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
527             ret.append(lib)
528
529     return ret
530
531
532
533 @conf
534 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
535                    headers=None, link=True, empty_decl=True, set_target=True):
536     """
537     check that the functions in 'list' are available in 'library'
538     if they are, then make that library available as a dependency
539
540     if the library is not available and mandatory==True, then
541     raise an error.
542
543     If the library is not available and mandatory==False, then
544     add the library to the list of dependencies to remove from
545     build rules
546
547     optionally check for the functions first in libc
548     """
549     remaining = TO_LIST(list)
550     liblist   = TO_LIST(library)
551
552     # check if some already found
553     for f in remaining[:]:
554         if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
555             remaining.remove(f)
556
557     # see if the functions are in libc
558     if checklibc:
559         for f in remaining[:]:
560             if CHECK_FUNC(conf, f, link=True, headers=headers):
561                 remaining.remove(f)
562
563     if remaining == []:
564         for lib in liblist:
565             if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
566                 SET_TARGET_TYPE(conf, lib, 'EMPTY')
567         return True
568
569     checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
570     for lib in liblist[:]:
571         if not lib in checklist and mandatory:
572             Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
573             sys.exit(1)
574
575     ret = True
576     for f in remaining:
577         if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
578             ret = False
579
580     return ret
581
582
583 @conf
584 def IN_LAUNCH_DIR(conf):
585     '''return True if this rule is being run from the launch directory'''
586     return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
587 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
588
589
590 @conf
591 def SAMBA_CONFIG_H(conf, path=None):
592     '''write out config.h in the right directory'''
593     # we don't want to produce a config.h in places like lib/replace
594     # when we are building projects that depend on lib/replace
595     if not IN_LAUNCH_DIR(conf):
596         return
597
598     if Options.options.developer:
599         # we add these here to ensure that -Wstrict-prototypes is not set during configure
600         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                         testflags=True)
602         if os.getenv('TOPLEVEL_BUILD'):
603             conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
604         conf.env.DEVELOPER_MODE = True
605
606     if Options.options.picky_developer:
607         conf.ADD_CFLAGS('-Werror', testflags=True)
608
609     if Options.options.fatal_errors:
610         conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
611
612     if Options.options.pedantic:
613         conf.ADD_CFLAGS('-W', testflags=True)
614
615     if path is None:
616         conf.write_config_header('config.h', top=True)
617     else:
618         conf.write_config_header(path)
619     conf.SAMBA_CROSS_CHECK_COMPLETE()
620
621
622 @conf
623 def CONFIG_PATH(conf, name, default):
624     '''setup a configurable path'''
625     if not name in conf.env:
626         if default[0] == '/':
627             conf.env[name] = default
628         else:
629             conf.env[name] = conf.env['PREFIX'] + default
630
631 @conf
632 def ADD_CFLAGS(conf, flags, testflags=False):
633     '''add some CFLAGS to the command line
634        optionally set testflags to ensure all the flags work
635     '''
636     if testflags:
637         ok_flags=[]
638         for f in flags.split():
639             if CHECK_CFLAGS(conf, f):
640                 ok_flags.append(f)
641         flags = ok_flags
642     if not 'EXTRA_CFLAGS' in conf.env:
643         conf.env['EXTRA_CFLAGS'] = []
644     conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
645
646 @conf
647 def ADD_LDFLAGS(conf, flags, testflags=False):
648     '''add some LDFLAGS to the command line
649        optionally set testflags to ensure all the flags work
650
651        this will return the flags that are added, if any
652     '''
653     if testflags:
654         ok_flags=[]
655         for f in flags.split():
656             if CHECK_LDFLAGS(conf, f):
657                 ok_flags.append(f)
658         flags = ok_flags
659     if not 'EXTRA_LDFLAGS' in conf.env:
660         conf.env['EXTRA_LDFLAGS'] = []
661     conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
662     return flags
663
664
665 @conf
666 def ADD_EXTRA_INCLUDES(conf, includes):
667     '''add some extra include directories to all builds'''
668     if not 'EXTRA_INCLUDES' in conf.env:
669         conf.env['EXTRA_INCLUDES'] = []
670     conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
671
672
673
674 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
675     '''work out the current flags. local flags are added first'''
676     if not 'EXTRA_CFLAGS' in bld.env:
677         list = []
678     else:
679         list = bld.env['EXTRA_CFLAGS'];
680     ret = TO_LIST(cflags)
681     ret.extend(list)
682     if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
683         ret.append('-fvisibility=hidden')
684     return ret
685
686
687 @conf
688 def CHECK_CC_ENV(conf):
689     """trim whitespaces from 'CC'.
690     The build farm sometimes puts a space at the start"""
691     if os.environ.get('CC'):
692         conf.env.CC = TO_LIST(os.environ.get('CC'))
693         if len(conf.env.CC) == 1:
694             # make for nicer logs if just a single command
695             conf.env.CC = conf.env.CC[0]
696
697
698 @conf
699 def SETUP_CONFIGURE_CACHE(conf, enable):
700     '''enable/disable cache of configure results'''
701     if enable:
702         # when -C is chosen, we will use a private cache and will
703         # not look into system includes. This roughtly matches what
704         # autoconf does with -C
705         cache_path = os.path.join(conf.blddir, '.confcache')
706         mkdir_p(cache_path)
707         Options.cache_global = os.environ['WAFCACHE'] = cache_path
708     else:
709         # when -C is not chosen we will not cache configure checks
710         # We set the recursion limit low to prevent waf from spending
711         # a lot of time on the signatures of the files.
712         Options.cache_global = os.environ['WAFCACHE'] = ''
713         preproc.recursion_limit = 1
714     # in either case we don't need to scan system includes
715     preproc.go_absolute = False