6ed719a80adde3c2984742ac94943a56b0d1e751
[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         # note that we do not add the -L in here, as that is added by the waf
475         # core. Adding it here would just change the order that it is put on the link line
476         # which can cause system paths to be added before internal libraries
477         extra_ccflags = TO_LIST(getattr(self.env, 'CCFLAGS_%s' % lib.upper(), []))
478         extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), []))
479         ccflags.extend(extra_ccflags)
480         ldflags.extend(extra_ldflags)
481     if 'EXTRA_LDFLAGS' in self.env:
482         ldflags.extend(self.env['EXTRA_LDFLAGS'])
483
484     ccflags = unique_list(ccflags)
485     ldflags = unique_list(ldflags)
486     return (ccflags, ldflags)
487
488
489 @conf
490 def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False):
491     '''check if a set of libraries exist as system libraries
492
493     returns the sublist of libs that do exist as a syslib or []
494     '''
495
496     fragment= '''
497 int foo()
498 {
499     int v = 2;
500     return v*2;
501 }
502 '''
503     ret = []
504     liblist  = TO_LIST(libs)
505     for lib in liblist[:]:
506         if GET_TARGET_TYPE(conf, lib) == 'SYSLIB':
507             ret.append(lib)
508             continue
509
510         (ccflags, ldflags) = library_flags(conf, lib)
511         if shlib:
512             res = conf.check(features='cc cshlib', fragment=fragment, lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
513         else:
514             res = conf.check(lib=lib, uselib_store=lib, ccflags=ccflags, ldflags=ldflags)
515
516         if not res:
517             if mandatory:
518                 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
519                 sys.exit(1)
520             if empty_decl:
521                 # if it isn't a mandatory library, then remove it from dependency lists
522                 if set_target:
523                     SET_TARGET_TYPE(conf, lib, 'EMPTY')
524         else:
525             conf.define('HAVE_LIB%s' % lib.upper().replace('-','_'), 1)
526             conf.env['LIB_' + lib.upper()] = lib
527             if set_target:
528                 conf.SET_TARGET_TYPE(lib, 'SYSLIB')
529             ret.append(lib)
530
531     return ret
532
533
534
535 @conf
536 def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False,
537                    headers=None, link=True, empty_decl=True, set_target=True):
538     """
539     check that the functions in 'list' are available in 'library'
540     if they are, then make that library available as a dependency
541
542     if the library is not available and mandatory==True, then
543     raise an error.
544
545     If the library is not available and mandatory==False, then
546     add the library to the list of dependencies to remove from
547     build rules
548
549     optionally check for the functions first in libc
550     """
551     remaining = TO_LIST(list)
552     liblist   = TO_LIST(library)
553
554     # check if some already found
555     for f in remaining[:]:
556         if CONFIG_SET(conf, 'HAVE_%s' % f.upper()):
557             remaining.remove(f)
558
559     # see if the functions are in libc
560     if checklibc:
561         for f in remaining[:]:
562             if CHECK_FUNC(conf, f, link=True, headers=headers):
563                 remaining.remove(f)
564
565     if remaining == []:
566         for lib in liblist:
567             if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl:
568                 SET_TARGET_TYPE(conf, lib, 'EMPTY')
569         return True
570
571     checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target)
572     for lib in liblist[:]:
573         if not lib in checklist and mandatory:
574             Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list))
575             sys.exit(1)
576
577     ret = True
578     for f in remaining:
579         if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link):
580             ret = False
581
582     return ret
583
584
585 @conf
586 def IN_LAUNCH_DIR(conf):
587     '''return True if this rule is being run from the launch directory'''
588     return os.path.realpath(conf.curdir) == os.path.realpath(Options.launch_dir)
589 Options.Handler.IN_LAUNCH_DIR = IN_LAUNCH_DIR
590
591
592 @conf
593 def SAMBA_CONFIG_H(conf, path=None):
594     '''write out config.h in the right directory'''
595     # we don't want to produce a config.h in places like lib/replace
596     # when we are building projects that depend on lib/replace
597     if not IN_LAUNCH_DIR(conf):
598         return
599
600     if Options.options.developer:
601         # we add these here to ensure that -Wstrict-prototypes is not set during configure
602         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',
603                         testflags=True)
604         conf.ADD_CFLAGS('-Wcast-qual', testflags=True)
605         conf.env.DEVELOPER_MODE = True
606
607     if Options.options.picky_developer:
608         conf.ADD_CFLAGS('-Werror', testflags=True)
609
610     if Options.options.fatal_errors:
611         conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
612
613     if Options.options.pedantic:
614         conf.ADD_CFLAGS('-W', testflags=True)
615
616     if path is None:
617         conf.write_config_header('config.h', top=True)
618     else:
619         conf.write_config_header(path)
620     conf.SAMBA_CROSS_CHECK_COMPLETE()
621
622
623 @conf
624 def CONFIG_PATH(conf, name, default):
625     '''setup a configurable path'''
626     if not name in conf.env:
627         if default[0] == '/':
628             conf.env[name] = default
629         else:
630             conf.env[name] = conf.env['PREFIX'] + default
631
632 @conf
633 def ADD_CFLAGS(conf, flags, testflags=False):
634     '''add some CFLAGS to the command line
635        optionally set testflags to ensure all the flags work
636     '''
637     if testflags:
638         ok_flags=[]
639         for f in flags.split():
640             if CHECK_CFLAGS(conf, f):
641                 ok_flags.append(f)
642         flags = ok_flags
643     if not 'EXTRA_CFLAGS' in conf.env:
644         conf.env['EXTRA_CFLAGS'] = []
645     conf.env['EXTRA_CFLAGS'].extend(TO_LIST(flags))
646
647 @conf
648 def ADD_LDFLAGS(conf, flags, testflags=False):
649     '''add some LDFLAGS to the command line
650        optionally set testflags to ensure all the flags work
651
652        this will return the flags that are added, if any
653     '''
654     if testflags:
655         ok_flags=[]
656         for f in flags.split():
657             if CHECK_LDFLAGS(conf, f):
658                 ok_flags.append(f)
659         flags = ok_flags
660     if not 'EXTRA_LDFLAGS' in conf.env:
661         conf.env['EXTRA_LDFLAGS'] = []
662     conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags))
663     return flags
664
665
666 @conf
667 def ADD_EXTRA_INCLUDES(conf, includes):
668     '''add some extra include directories to all builds'''
669     if not 'EXTRA_INCLUDES' in conf.env:
670         conf.env['EXTRA_INCLUDES'] = []
671     conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes))
672
673
674
675 def CURRENT_CFLAGS(bld, target, cflags, hide_symbols=False):
676     '''work out the current flags. local flags are added first'''
677     if not 'EXTRA_CFLAGS' in bld.env:
678         list = []
679     else:
680         list = bld.env['EXTRA_CFLAGS'];
681     ret = TO_LIST(cflags)
682     ret.extend(list)
683     if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR:
684         ret.append('-fvisibility=hidden')
685     return ret
686
687
688 @conf
689 def CHECK_CC_ENV(conf):
690     """trim whitespaces from 'CC'.
691     The build farm sometimes puts a space at the start"""
692     if os.environ.get('CC'):
693         conf.env.CC = TO_LIST(os.environ.get('CC'))
694         if len(conf.env.CC) == 1:
695             # make for nicer logs if just a single command
696             conf.env.CC = conf.env.CC[0]
697
698
699 @conf
700 def SETUP_CONFIGURE_CACHE(conf, enable):
701     '''enable/disable cache of configure results'''
702     if enable:
703         # when -C is chosen, we will use a private cache and will
704         # not look into system includes. This roughtly matches what
705         # autoconf does with -C
706         cache_path = os.path.join(conf.blddir, '.confcache')
707         mkdir_p(cache_path)
708         Options.cache_global = os.environ['WAFCACHE'] = cache_path
709     else:
710         # when -C is not chosen we will not cache configure checks
711         # We set the recursion limit low to prevent waf from spending
712         # a lot of time on the signatures of the files.
713         Options.cache_global = os.environ['WAFCACHE'] = ''
714         preproc.recursion_limit = 1
715     # in either case we don't need to scan system includes
716     preproc.go_absolute = False
717
718
719 @conf
720 def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf):
721     # we don't want any libraries or modules to rely on runtime
722     # resolution of symbols
723     if sys.platform != "openbsd4":
724         conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True)
725
726     if sys.platform != "openbsd4" and conf.env.undefined_ignore_ldflags == []:
727         if conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup']):
728             conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup']