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