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