build: result of hack session with ita
[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, Logs, sys, Configure, Options, string, Task, Utils, optparse
5 from Configure import conf
6 from Logs import debug
7 from TaskGen import extension
8
9 # bring in the other samba modules
10 from samba_utils import *
11 # should be enabled from the above?
12 from samba_autoconf import *
13 from samba_patterns import *
14 from samba_pidl import *
15 from samba_asn1 import *
16 from samba_autoproto import *
17
18 LIB_PATH="shared"
19
20
21 #################################################################
22 # create the samba build environment
23 @conf
24 def SAMBA_BUILD_ENV(conf):
25     libpath="%s/%s" % (conf.blddir, LIB_PATH)
26     conf.env['BUILD_DIRECTORY'] = conf.blddir
27     if not os.path.exists(libpath):
28         os.mkdir(libpath)
29
30 ##############################################
31 # remove .. elements from a path list
32 def NORMPATH(bld, ilist):
33     return " ".join([os.path.normpath(p) for p in ilist.split(" ")])
34 Build.BuildContext.NORMPATH = NORMPATH
35
36 ################################################################
37 # add an init_function to the list for a subsystem
38 def ADD_INIT_FUNCTION(bld, subsystem, init_function):
39     if init_function is None:
40         return
41     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
42     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
43     if not subsystem in cache:
44         cache[subsystem] = ''
45     cache[subsystem] += '%s,' % init_function
46 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
47
48 ################################################################
49 # recursively build the dependency list for a target
50 def FULL_DEPENDENCIES(bld, cache, target, chain, path):
51     if not target in cache:
52         return {}
53     deps = cache[target].copy()
54     for t in cache[target]:
55         bld.ASSERT(t not in chain, "Circular dependency for %s: %s->%s" % (t, path, t));
56         c2 = chain.copy()
57         c2[t] = True
58         dict_concat(deps, FULL_DEPENDENCIES(bld, cache, t, c2, "%s->%s" % (path, t)))
59     return deps
60
61 ############################################################
62 # check our build dependencies for circular dependencies
63 def CHECK_TARGET_DEPENDENCY(bld, target):
64     cache = LOCAL_CACHE(bld, 'LIB_DEPS')
65     return FULL_DEPENDENCIES(bld, cache, target, { target:True }, target)
66
67 ############################################################
68 # check that all dependencies have been declared
69 def CHECK_DEPENDENCIES(bld):
70     cache = LOCAL_CACHE(bld, 'LIB_DEPS')
71     target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
72     debug('deps: Checking dependencies')
73     for t in cache:
74         deps = CHECK_TARGET_DEPENDENCY(bld, t)
75         for d in deps:
76             if not d in target_cache:
77                 print "WARNING: Dependency '%s' of target '%s' not declared" % (d, t)
78             #ASSERT(bld, d in target_cache,
79             #       "Dependency '%s' of target '%s' not declared" % (d, t))
80     debug("deps: Dependencies checked for %u targets" % len(target_cache))
81 Build.BuildContext.CHECK_DEPENDENCIES = CHECK_DEPENDENCIES
82
83
84 ############################################################
85 # pre-declare a target as being of a particular type
86 def PREDECLARE(bld, target, type):
87     cache = LOCAL_CACHE(bld, 'PREDECLARED_TARGET')
88     target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
89     ASSERT(bld, not target in target_cache, "Target '%s' is already declared" % target)
90     ASSERT(bld, not target in cache, "Target '%s' already predeclared" % target)
91     cache[target] = type
92 Build.BuildContext.PREDECLARE = PREDECLARE
93
94
95
96 ################################################################
97 # add to the dependency list. Return a new dependency list with
98 # any circular dependencies removed
99 # returns a tuple containing (systemdeps, localdeps, add_objects)
100 def ADD_DEPENDENCIES(bld, name, deps):
101     debug('deps: Calculating dependencies for %s' % name)
102     lib_deps = LOCAL_CACHE(bld, 'LIB_DEPS')
103     if not name in lib_deps:
104         lib_deps[name] = {}
105     list = deps.split()
106     list2 = []
107     for d in list:
108         lib_deps[name][d] = True;
109         try:
110             CHECK_TARGET_DEPENDENCY(bld, name)
111             list2.append(d)
112         except AssertionError:
113             sys.stderr.write("Removing dependency %s from target %s\n" % (d, name))
114             del(lib_deps[name][d])
115
116     target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
117
118     # extract out the system dependencies
119     sysdeps = []
120     localdeps = []
121     add_objects = []
122     cache = LOCAL_CACHE(bld, 'EMPTY_TARGETS')
123     predeclare = LOCAL_CACHE(bld, 'PREDECLARED_TARGET')
124     for d in list2:
125         recurse = False
126         # strip out any dependencies on empty libraries
127         if d in cache:
128             debug("deps: Removing empty dependency '%s' from '%s'" % (d, name))
129             continue
130         type = None
131
132         if d in target_cache:
133             type = target_cache[d]
134         elif d in predeclare:
135             type = predeclare[d]
136         else:
137             type = 'SUBSYSTEM'
138             LOCAL_CACHE_SET(bld, 'ASSUMED_TARGET', d, type)
139
140         if type == 'SYSLIB':
141             sysdeps.append(d)
142         elif type == 'LIBRARY':
143             localdeps.append(d)
144         elif type == 'SUBSYSTEM':
145             add_objects.append(d)
146             recurse = True
147         elif type == 'MODULE':
148             add_objects.append(d)
149             recurse = True
150         elif type == 'PYTHON':
151             pass
152         elif type == 'ASN1':
153             pass
154         elif type == 'BINARY':
155             pass
156         else:
157             ASSERT(bld, False, "Unknown target type '%s' for dependency %s" % (
158                     type, d))
159
160         # for some types we have to build the list recursively
161         if recurse and (d in lib_deps):
162             rec_deps = ' '.join(lib_deps[d].keys())
163             (rec_sysdeps, rec_localdeps, rec_add_objects) = ADD_DEPENDENCIES(bld, d, rec_deps)
164             sysdeps.extend(rec_sysdeps.split())
165             localdeps.extend(rec_localdeps.split())
166             add_objects.extend(rec_add_objects.split())
167
168     debug('deps: Dependencies for %s: sysdeps: %u  localdeps: %u  add_objects=%u' % (
169             name, len(sysdeps), len(localdeps), len(add_objects)))
170     return (' '.join(sysdeps), ' '.join(localdeps), ' '.join(add_objects))
171
172
173 #################################################################
174 # return a include list for a set of library dependencies
175 def SAMBA_LIBRARY_INCLUDE_LIST(bld, deps):
176     ret = bld.curdir + ' '
177     cache = LOCAL_CACHE(bld, 'INCLUDE_LIST')
178     for l in deps.split():
179         if l in cache:
180             ret = ret + cache[l] + ' '
181     if 'EXTRA_INCLUDES' in bld.env:
182         ret += ' ' + ' '.join(bld.env['EXTRA_INCLUDES'])
183     return ret
184 Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
185
186 #################################################################
187 # define a Samba library
188 def SAMBA_LIBRARY(bld, libname, source,
189                   deps='',
190                   public_deps='',
191                   includes='.',
192                   public_headers=None,
193                   vnum=None,
194                   cflags='',
195                   output_type=None,
196                   realname=None,
197                   autoproto=None,
198                   group='main',
199                   depends_on=''):
200     if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'):
201         return
202
203     # remember empty libraries, so we can strip the dependencies
204     if (source == '') or (source == []):
205         LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', libname, True)
206         return
207
208     (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, libname, deps)
209
210     ilist = bld.SUBDIR(bld.curdir, includes) + ' ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps)
211     ilist = bld.NORMPATH(ilist)
212
213     # this print below should show that we're runnig this code
214     print "Setting build group for library %s to %s" % (libname, group), bld.path
215     bld.SET_BUILD_GROUP(group)   # <- here
216     bld(
217         features = 'cc cshlib',
218         source = source,
219         target=libname,
220         uselib_local = localdeps,
221         uselib = sysdeps,
222         add_objects = add_objects,
223         ccflags = CURRENT_CFLAGS(bld, cflags),
224         includes=ilist + ' . #',
225         depends_on=depends_on,
226         vnum=vnum)
227
228     # I have to set it each time? I expect it to be still
229     # set from the few lines above
230
231     # put a link to the library in bin/shared
232     soext=""
233     if vnum is not None:
234         soext = '.' + vnum.split('.')[0]
235
236     t = bld(
237         source = 'lib%s.so' % libname,
238         rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s' % (soext, LIB_PATH, libname, soext),
239 #        rule = 'ln -sf ../%s.so%s %s/lib%s.so%s' % (libname, soext, LIB_PATH, libname, soext),
240         shell = True,
241         after = 'cc_link',
242         always = True,
243         name = 'fff' + libname,
244         )
245     #print t.rule
246     LOCAL_CACHE_SET(bld, 'INCLUDE_LIST', libname, ilist)
247
248 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
249
250 #################################################################
251 # define a Samba binary
252 def SAMBA_BINARY(bld, binname, source,
253                  deps='',
254                  includes='',
255                  public_headers=None,
256                  modules=None,
257                  installdir=None,
258                  ldflags=None,
259                  cflags='',
260                  autoproto=None,
261                  use_hostcc=None,
262                  compiler=None,
263                  group='main',
264                  manpages=None):
265     ilist = includes + ' ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps)
266     ilist = bld.NORMPATH(ilist)
267
268     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
269         return
270
271     (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, binname, deps)
272
273     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
274     if modules is not None:
275         for m in modules.split():
276             bld.ASSERT(m in cache,
277                        "No init_function defined for module '%s' in binary '%s'" % (m, binname))
278             cflags += ' -DSTATIC_%s_MODULES="%s"' % (m, cache[m])
279
280     bld.SET_BUILD_GROUP(group)
281     bld(
282         features = 'cc cprogram',
283         source = source,
284         target = binname,
285         uselib_local = localdeps,
286         uselib = sysdeps,
287         includes = ilist + ' . #',
288         ccflags = CURRENT_CFLAGS(bld, cflags),
289         add_objects = add_objects,
290         top=True)
291
292     if not Options.is_install:
293         bld(
294             source = binname,
295             rule = 'rm -f %s && cp ${SRC} .' % (binname),
296             shell = True,
297             after = 'cc_link',
298             always = True,
299             ext_in = '.bin',
300             name = binname + ".copy",
301             depends_on = binname
302             )
303 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
304
305
306 #################################################################
307 # define a Samba python module
308 def SAMBA_PYTHON(bld, name, source,
309                  deps='',
310                  public_deps='',
311                  realname=''):
312
313     if not SET_TARGET_TYPE(bld, name, 'PYTHON'):
314         return
315
316     (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, name, deps)
317
318     return
319 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
320
321 #################################################################
322 # define a Samba ET target
323 def SAMBA_ERRTABLE(bld, name, source,
324                options='',
325                directory=''):
326 #    print "Skipping ERRTABLE rule for %s with source=%s" % (name, source)
327 #    return
328     if not SET_TARGET_TYPE(bld, name, 'ET'):
329         return
330     bld.SET_BUILD_GROUP('build_source')
331     bld(
332         features = 'cc',
333         source   = source,
334         target   = name
335     )
336 Build.BuildContext.SAMBA_ERRTABLE = SAMBA_ERRTABLE
337
338
339
340
341 ################################################################
342 # build a C prototype file automatically
343 def AUTOPROTO(bld, header, source):
344     if header is not None:
345         bld.SET_BUILD_GROUP('prototypes')
346         bld(
347             source = source,
348             target = header,
349             rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
350             )
351 Build.BuildContext.AUTOPROTO = AUTOPROTO
352
353
354 #################################################################
355 # define a Samba module.
356 def SAMBA_MODULE(bld, modname, source,
357                  deps='',
358                  includes='.',
359                  subsystem=None,
360                  init_function=None,
361                  autoproto=None,
362                  aliases=None,
363                  cflags='',
364                  output_type=None):
365
366     if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
367         return
368
369     # remember empty modules, so we can strip the dependencies
370     if (source == '') or (source == []):
371         LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', modname, True)
372         return
373
374     (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
375
376     ilist = bld.SUBDIR(bld.curdir, includes) + ' ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps)
377     ilist = bld.NORMPATH(ilist)
378     bld.SET_BUILD_GROUP('main')
379     bld(
380         features = 'cc',
381         source = source,
382         target=modname,
383         ccflags = CURRENT_CFLAGS(bld, cflags),
384         includes=ilist + ' . #')
385 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
386
387
388 #################################################################
389 # define a Samba subsystem
390 def SAMBA_SUBSYSTEM(bld, modname, source,
391                     deps='',
392                     public_deps='',
393                     includes='.',
394                     public_headers=None,
395                     cflags='',
396                     group='main',
397                     config_option=None,
398                     init_function_sentinal=None,
399                     heimdal_autoproto=None,
400                     heimdal_autoproto_private=None,
401                     autoproto=None,
402                     depends_on=''):
403
404     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
405         return
406
407     # if the caller specifies a config_option, then we create a blank
408     # subsystem if that configuration option was found at configure time
409     if (config_option is not None) and bld.CONFIG_SET(config_option):
410             source = ''
411
412     # remember empty subsystems, so we can strip the dependencies
413     if (source == '') or (source == []):
414         LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', modname, True)
415         return
416
417     (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
418
419     ilist = bld.SUBDIR(bld.curdir, includes) + ' ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps)
420     ilist = bld.NORMPATH(ilist)
421     bld.SET_BUILD_GROUP(group)
422     t = bld(
423         features = 'cc',
424         source = source,
425         target=modname,
426         ccflags = CURRENT_CFLAGS(bld, cflags),
427         includes=ilist + ' . #',
428         depends_on=depends_on)
429     LOCAL_CACHE_SET(bld, 'INCLUDE_LIST', modname, ilist)
430
431     if heimdal_autoproto is not None:
432         bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source)
433     if heimdal_autoproto_private is not None:
434         bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
435     if autoproto is not None:
436         bld.SAMBA_AUTOPROTO(autoproto, source)
437     return t
438
439 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
440
441
442 ###############################################################
443 # add a new set of build rules from a subdirectory
444 # the @runonce decorator ensures we don't end up
445 # with duplicate rules
446 def BUILD_SUBDIR(bld, dir):
447     path = os.path.normpath(bld.curdir + '/' + dir)
448     cache = LOCAL_CACHE(bld, 'SUBDIR_LIST')
449     if path in cache: return
450     cache[path] = True
451     debug("build: Processing subdirectory %s" % dir)
452     bld.add_subdirs(dir)
453
454 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
455
456
457 ##########################################################
458 # add a new top level command to waf
459 def ADD_COMMAND(opt, name, function):
460     Utils.g_module.__dict__[name] = function
461     opt.name = function
462 Options.Handler.ADD_COMMAND = ADD_COMMAND
463
464 ###########################################################
465 # setup build groups used to ensure that the different build
466 # phases happen consecutively
467 @runonce
468 def SETUP_BUILD_GROUPS(bld):
469     bld.p_ln = bld.srcnode # we do want to see all targets!
470     bld.env['USING_BUILD_GROUPS'] = True
471     bld.add_group('setup')
472     bld.add_group('base_libraries')
473     bld.add_group('build_compilers')
474     bld.add_group('build_source')
475     bld.add_group('prototypes')
476     bld.add_group('main')
477     bld.add_group('final')
478 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
479
480
481 ###########################################################
482 # set the current build group
483 def SET_BUILD_GROUP(bld, group):
484     if not 'USING_BUILD_GROUPS' in bld.env:
485         return
486     bld.set_group(group)
487 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
488