build: fixed ifaddrs.h for heimdal (from template)
[obnox/samba/samba-obnox.git] / buildtools / wafsamba / wafsamba.py
1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
3
4 import Build, os, Options, Task, Utils, cc, TaskGen
5 from Configure import conf
6 from Logs import debug
7 from samba_utils import SUBST_VARS_RECURSIVE
8
9 # bring in the other samba modules
10 from samba_optimisation import *
11 from samba_utils import *
12 from samba_autoconf import *
13 from samba_patterns import *
14 from samba_pidl import *
15 from samba_errtable import *
16 from samba_asn1 import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20
21 LIB_PATH="shared"
22
23
24
25 #################################################################
26 # create the samba build environment
27 @conf
28 def SAMBA_BUILD_ENV(conf):
29     conf.env['BUILD_DIRECTORY'] = conf.blddir
30     mkdir_p(os.path.join(conf.blddir, LIB_PATH))
31     mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
32     # this allows all of the bin/shared and bin/python targets
33     # to be expressed in terms of build directory paths
34     for p in ['python','shared']:
35         link_target = os.path.join(conf.blddir, 'default/' + p)
36         if not os.path.lexists(link_target):
37             os.symlink('../' + p, link_target)
38
39
40
41 ################################################################
42 # add an init_function to the list for a subsystem
43 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
44     if init_function is None:
45         return
46     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
47     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
48     if not subsystem in cache:
49         cache[subsystem] = []
50     cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
51 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
52
53
54 #################################################################
55 # define a Samba library
56 def SAMBA_LIBRARY(bld, libname, source,
57                   deps='',
58                   public_deps='',
59                   includes='',
60                   public_headers=None,
61                   vnum=None,
62                   cflags='',
63                   external_library=False,
64                   realname=None,
65                   autoproto=None,
66                   group='main',
67                   depends_on='',
68                   local_include=True,
69                   install_path=None,
70                   install=True,
71                   enabled=True):
72
73     if not enabled:
74         SET_TARGET_TYPE(bld, libname, 'DISABLED')
75         return
76
77     # remember empty libraries, so we can strip the dependencies
78     if (source == '') or (source == []):
79         SET_TARGET_TYPE(bld, libname, 'EMPTY')
80         return
81
82     if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'):
83         return
84
85     obj_target = libname + '.objlist'
86
87     # first create a target for building the object files for this library
88     # by separating in this way, we avoid recompiling the C files
89     # separately for the install library and the build library
90     bld.SAMBA_SUBSYSTEM(obj_target,
91                         source         = source,
92                         deps           = deps,
93                         public_deps    = public_deps,
94                         includes       = includes,
95                         public_headers = public_headers,
96                         cflags         = cflags,
97                         group          = group,
98                         autoproto      = autoproto,
99                         depends_on     = depends_on,
100                         local_include  = local_include)
101
102     # the library itself will depend on that object target
103     deps += ' ' + public_deps
104     deps = TO_LIST(deps)
105     deps.append(obj_target)
106
107     bld.SET_BUILD_GROUP(group)
108     t = bld(
109         features        = 'cc cshlib symlink_lib',
110         source          = [],
111         target          = libname,
112         samba_cflags    = CURRENT_CFLAGS(bld, libname, cflags),
113         depends_on      = depends_on,
114         samba_deps      = deps,
115         samba_includes  = includes,
116         local_include   = local_include,
117         vnum            = vnum,
118         install_path    = None
119         )
120
121     if install_path is None:
122         install_path = '${LIBDIR}'
123     install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
124
125     if install:
126         # create a separate install library, which may have
127         # different rpath settings
128         SET_TARGET_TYPE(bld, libname + '.inst', 'LIBRARY')
129         t = bld(
130             features        = 'cc cshlib',
131             source          = [],
132             target          = libname + '.inst',
133             samba_cflags    = CURRENT_CFLAGS(bld, libname, cflags),
134             depends_on      = depends_on,
135             samba_deps      = deps,
136             samba_includes  = includes,
137             local_include   = local_include,
138             vnum            = vnum,
139             install_as      = libname,
140             install_path    = None,
141             )
142         t.env['RPATH'] = install_rpath(bld)
143
144         if vnum:
145             vnum_base = vnum.split('.')[0]
146             install_name = 'lib%s.so.%s' % (libname, vnum)
147             install_link = 'lib%s.so.%s' % (libname, vnum_base)
148         else:
149             install_name = 'lib%s.so' % libname
150             install_link = None
151
152         bld.install_as(os.path.join(install_path, install_name),
153                        'lib%s.inst.so' % libname)
154         if install_link:
155             bld.symlink_as(os.path.join(install_path, install_link), install_name)
156
157
158     if autoproto is not None:
159         bld.SAMBA_AUTOPROTO(autoproto, source)
160
161 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
162
163
164 #################################################################
165 # define a Samba binary
166 def SAMBA_BINARY(bld, binname, source,
167                  deps='',
168                  includes='',
169                  public_headers=None,
170                  modules=None,
171                  installdir=None,
172                  ldflags=None,
173                  cflags='',
174                  autoproto=None,
175                  use_hostcc=None,
176                  compiler=None,
177                  group='binaries',
178                  manpages=None,
179                  local_include=True,
180                  subsystem_name=None,
181                  needs_python=False,
182                  install=True,
183                  install_path=None):
184
185     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
186         return
187
188     features = 'cc cprogram'
189     if needs_python:
190         features += ' pyembed'
191
192     bld.SET_BUILD_GROUP(group)
193
194     obj_target = binname + '.objlist'
195
196     # first create a target for building the object files for this binary
197     # by separating in this way, we avoid recompiling the C files
198     # separately for the install binary and the build binary
199     bld.SAMBA_SUBSYSTEM(obj_target,
200                         source         = source,
201                         deps           = deps,
202                         includes       = includes,
203                         cflags         = cflags,
204                         group          = group,
205                         autoproto      = autoproto,
206                         subsystem_name = subsystem_name,
207                         needs_python   = needs_python,
208                         local_include  = local_include)
209
210     # the library itself will depend on that object target
211     deps = TO_LIST(deps)
212     deps.append(obj_target)
213
214     bld(
215         features       = features + ' symlink_bin',
216         source         = [],
217         target         = binname,
218         samba_cflags   = CURRENT_CFLAGS(bld, binname, cflags),
219         samba_deps     = deps,
220         samba_includes = includes,
221         local_include  = local_include,
222         samba_modules  = modules,
223         top            = True,
224         samba_subsystem= subsystem_name,
225         install_path   = None
226         )
227
228     if install_path is None:
229         install_path = '${BINDIR}'
230     install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
231
232     if install:
233         # we create a separate 'install' binary, which
234         # will have different rpath settings
235         SET_TARGET_TYPE(bld, binname + '.inst', 'BINARY')
236         t = bld(
237             features       = features,
238             source         = [],
239             target         = binname + '.inst',
240             samba_cflags   = CURRENT_CFLAGS(bld, binname, cflags),
241             samba_deps     = deps,
242             samba_includes = includes,
243             local_include  = local_include,
244             samba_modules  = modules,
245             top            = True,
246             samba_subsystem= subsystem_name,
247             install_path   = None
248             )
249         t.env['RPATH'] = install_rpath(bld)
250
251         bld.install_as(os.path.join(install_path, binname),
252                        binname + '.inst',
253                        chmod=0755)
254
255     # setup the subsystem_name as an alias for the real
256     # binary name, so it can be found when expanding
257     # subsystem dependencies
258     if subsystem_name is not None:
259         bld.TARGET_ALIAS(subsystem_name, binname)
260
261     if autoproto is not None:
262         bld.SAMBA_AUTOPROTO(autoproto, source)
263 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
264
265
266 #################################################################
267 # define a Samba module.
268 def SAMBA_MODULE(bld, modname, source,
269                  deps='',
270                  includes='',
271                  subsystem=None,
272                  init_function=None,
273                  autoproto=None,
274                  autoproto_extra_source='',
275                  aliases=None,
276                  cflags='',
277                  internal_module=True,
278                  local_include=True,
279                  enabled=True):
280
281     if internal_module:
282         # treat internal modules as subsystems for now
283         SAMBA_SUBSYSTEM(bld, modname, source,
284                         deps=deps,
285                         includes=includes,
286                         autoproto=autoproto,
287                         autoproto_extra_source=autoproto_extra_source,
288                         cflags=cflags,
289                         local_include=local_include,
290                         enabled=enabled)
291         # even though we're treating it as a subsystem, we need to
292         # add it to the init_function list
293         # TODO: we should also create an implicit dependency
294         # between the subsystem target and this target
295         if enabled:
296             bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
297         return
298
299     if not enabled:
300         SET_TARGET_TYPE(bld, modname, 'DISABLED')
301         return
302
303     # remember empty modules, so we can strip the dependencies
304     if (source == '') or (source == []):
305         SET_TARGET_TYPE(bld, modname, 'EMPTY')
306         return
307
308     if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
309         return
310
311
312     bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
313
314     if subsystem is not None:
315         deps += ' ' + subsystem
316
317     bld.SET_BUILD_GROUP('main')
318     bld(
319         features       = 'cc',
320         source         = source,
321         target         = modname,
322         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
323         samba_includes = includes,
324         local_include  = local_include,
325         samba_deps     = TO_LIST(deps)
326         )
327
328     if autoproto is not None:
329         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
330
331 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
332
333
334 #################################################################
335 # define a Samba subsystem
336 def SAMBA_SUBSYSTEM(bld, modname, source,
337                     deps='',
338                     public_deps='',
339                     includes='',
340                     public_headers=None,
341                     cflags='',
342                     cflags_end=None,
343                     group='main',
344                     init_function_sentinal=None,
345                     heimdal_autoproto=None,
346                     heimdal_autoproto_options=None,
347                     heimdal_autoproto_private=None,
348                     autoproto=None,
349                     autoproto_extra_source='',
350                     depends_on='',
351                     local_include=True,
352                     local_include_first=True,
353                     subsystem_name=None,
354                     enabled=True,
355                     needs_python=False):
356
357     if not enabled:
358         SET_TARGET_TYPE(bld, modname, 'DISABLED')
359         return
360
361     # remember empty subsystems, so we can strip the dependencies
362     if (source == '') or (source == []):
363         SET_TARGET_TYPE(bld, modname, 'EMPTY')
364         return
365
366     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
367         return
368
369     deps += ' ' + public_deps
370
371     bld.SET_BUILD_GROUP(group)
372
373     features = 'cc'
374     if needs_python:
375         features += ' pyext'
376
377     t = bld(
378         features       = features,
379         source         = source,
380         target         = modname,
381         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
382         depends_on     = depends_on,
383         samba_deps     = TO_LIST(deps),
384         samba_includes = includes,
385         local_include  = local_include,
386         local_include_first  = local_include_first,
387         samba_subsystem= subsystem_name
388         )
389
390     if cflags_end is not None:
391         t.samba_cflags.extend(TO_LIST(cflags_end))
392
393     if heimdal_autoproto is not None:
394         bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source, options=heimdal_autoproto_options)
395     if heimdal_autoproto_private is not None:
396         bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
397     if autoproto is not None:
398         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
399     return t
400
401 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
402
403
404 def SAMBA_GENERATOR(bld, name, rule, source, target,
405                     group='build_source', enabled=True):
406     '''A generic source generator target'''
407
408     if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
409         return
410
411     if not enabled:
412         return False
413
414     bld.SET_BUILD_GROUP(group)
415     bld(
416         rule=rule,
417         source=source,
418         target=target,
419         before='cc',
420         ext_out='.c',
421         name=name)
422 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
423
424
425
426 ###############################################################
427 # add a new set of build rules from a subdirectory
428 # the @runonce decorator ensures we don't end up
429 # with duplicate rules
430 def BUILD_SUBDIR(bld, dir):
431     path = os.path.normpath(bld.curdir + '/' + dir)
432     cache = LOCAL_CACHE(bld, 'SUBDIR_LIST')
433     if path in cache: return
434     cache[path] = True
435     debug("build: Processing subdirectory %s" % dir)
436     bld.add_subdirs(dir)
437
438 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
439
440
441 ##########################################################
442 # add a new top level command to waf
443 def ADD_COMMAND(opt, name, function):
444     Utils.g_module.__dict__[name] = function
445     opt.name = function
446 Options.Handler.ADD_COMMAND = ADD_COMMAND
447
448 ###########################################################
449 # setup build groups used to ensure that the different build
450 # phases happen consecutively
451 @runonce
452 def SETUP_BUILD_GROUPS(bld):
453     bld.p_ln = bld.srcnode # we do want to see all targets!
454     bld.env['USING_BUILD_GROUPS'] = True
455     bld.add_group('setup')
456     bld.add_group('base_libraries')
457     bld.add_group('build_compilers')
458     bld.add_group('build_source')
459     bld.add_group('prototypes')
460     bld.add_group('main')
461     bld.add_group('binaries')
462     bld.add_group('final')
463 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
464
465
466 ###########################################################
467 # set the current build group
468 def SET_BUILD_GROUP(bld, group):
469     if not 'USING_BUILD_GROUPS' in bld.env:
470         return
471     bld.set_group(group)
472 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
473
474
475 def h_file(filename):
476     import stat
477     st = os.stat(filename)
478     if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
479     m = Utils.md5()
480     m.update(str(st.st_mtime))
481     m.update(str(st.st_size))
482     m.update(filename)
483     return m.digest()
484
485 @conf
486 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
487     Utils.h_file = h_file
488
489
490 ##############################
491 # handle the creation of links for libraries and binaries
492 # note that we use a relative symlink path to allow the whole tree
493 # to me moved/copied elsewhere without breaking the links
494 t = Task.simple_task_type('symlink_lib', 'ln -sf ${LINK_SOURCE} ${LINK_TARGET}',
495                           color='PINK', ext_in='.bin')
496 t.quiet = True
497
498 @feature('symlink_lib')
499 @after('apply_link')
500 def symlink_lib(self):
501     tsk = self.create_task('symlink_lib', self.link_task.outputs[0])
502
503     # calculat the link target and put it in the environment
504     soext=""
505     vnum = getattr(self, 'vnum', None)
506     if vnum is not None:
507         soext = '.' + vnum.split('.')[0]
508
509     link_target = getattr(self, 'link_name', '')
510     if link_target == '':
511         link_target = '%s/lib%s.so%s' % (LIB_PATH, self.sname, soext)
512
513
514     link_source = os_path_relpath(self.link_task.outputs[0].abspath(self.env),
515                                   os.path.join(self.env.BUILD_DIRECTORY, link_target))
516
517     tsk.env.LINK_TARGET = link_target
518     tsk.env.LINK_SOURCE = link_source[3:]
519     debug('task_gen: LINK for %s is %s -> %s',
520           self.name, tsk.env.LINK_SOURCE, tsk.env.LINK_TARGET)
521
522
523 t = Task.simple_task_type('symlink_bin', 'ln -sf ${SRC} ${BIN_TARGET}',
524                           color='PINK', ext_in='.bin')
525 t.quiet = True
526
527 @feature('symlink_bin')
528 @after('apply_link')
529 def symlink_bin(self):
530     if Options.is_install:
531         # we don't want to copy the install binary, as
532         # that has the install rpath, not the build rpath
533         # The rpath of the binaries in bin/default/foo/blah is different
534         # during the install phase, as distros insist on not using rpath in installed binaries
535         return
536     tsk = self.create_task('symlink_bin', self.link_task.outputs[0])
537
538     tsk.env.BIN_TARGET = self.target
539     debug('task_gen: BIN_TARGET for %s is %s', self.name, tsk.env.BIN_TARGET)
540
541
542
543
544 t = Task.simple_task_type('copy_script', 'ln -sf ${SRC[0].abspath(env)} ${LINK_TARGET}',
545                           color='PINK', ext_in='.bin', shell=True)
546 t.quiet = True
547
548 @feature('copy_script')
549 @before('apply_link')
550 def copy_script(self):
551     tsk = self.create_task('copy_script', self.allnodes[0])
552     tsk.env.TARGET = self.target
553
554 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
555     '''used to copy scripts from the source tree into the build directory
556        for use by selftest'''
557
558     source = bld.path.ant_glob(pattern)
559
560     bld.SET_BUILD_GROUP('build_source')
561     for s in TO_LIST(source):
562         iname = s
563         if installname != None:
564             iname = installname
565         target = os.path.join(installdir, iname)
566         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
567         mkdir_p(tgtdir)
568         t = bld(features='copy_script',
569                 source       = s,
570                 target       = target,
571                 always       = True,
572                 install_path = None)
573         t.env.LINK_TARGET = target
574
575 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
576