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