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