1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
4 import Build, os, Logs, sys, Configure, Options, string, Task, Utils, optparse
5 from Configure import conf
7 from TaskGen import extension
9 # bring in the other samba modules
10 from samba_utils import *
11 from samba_autoconf import *
12 from samba_patterns import *
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')
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))
27 assumed = LOCAL_CACHE(ctx, 'ASSUMED_TARGET')
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))
42 #################################################################
43 # create the samba build environment
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):
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
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:
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:
66 cache[subsystem] += '%s,' % init_function
67 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
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:
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));
79 dict_concat(deps, FULL_DEPENDENCIES(bld, cache, t, c2, "%s->%s" % (path, t)))
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)
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')
95 deps = CHECK_TARGET_DEPENDENCY(bld, t)
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
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)
113 Build.BuildContext.PREDECLARE = PREDECLARE
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:
129 lib_deps[name][d] = True;
131 CHECK_TARGET_DEPENDENCY(bld, name)
133 except AssertionError:
134 debug("deps: Removing dependency %s from target %s" % (d, name))
135 del(lib_deps[name][d])
137 # extract out the system dependencies
141 cache = LOCAL_CACHE(bld, 'EMPTY_TARGETS')
142 target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
143 predeclare = LOCAL_CACHE(bld, 'PREDECLARED_TARGET')
146 # strip out any dependencies on empty libraries
148 debug("deps: Removing empty dependency '%s' from '%s'" % (d, name))
152 if d in target_cache:
153 type = target_cache[d]
154 elif d in predeclare:
158 LOCAL_CACHE_SET(bld, 'ASSUMED_TARGET', d, type)
162 elif type == 'LIBRARY':
164 elif type == 'SUBSYSTEM':
165 add_objects.append(d)
167 elif type == 'MODULE':
168 add_objects.append(d)
170 elif type == 'PYTHON':
174 elif type == 'BINARY':
177 ASSERT(bld, False, "Unknown target type '%s' for dependency %s" % (
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())
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))
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():
200 ret = ret + cache[l] + ' '
202 Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
204 #################################################################
205 # define a Samba library
206 def SAMBA_LIBRARY(bld, libname, source_list,
216 if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'):
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)
224 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, libname, deps)
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')
230 features = 'cc cshlib',
231 source = source_list,
233 uselib_local = localdeps,
235 add_objects = add_objects,
236 ccflags = CURRENT_CFLAGS(bld, cflags),
237 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist,
240 # put a link to the library in bin/shared
243 soext = '.' + vnum.split('.')[0]
244 bld.SET_BUILD_GROUP('final')
246 source = 'lib%s.so' % libname,
247 rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s' %
248 (soext, LIB_PATH, libname, soext),
252 LOCAL_CACHE_SET(bld, 'INCLUDE_LIST', libname, ilist)
254 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
257 #################################################################
258 # define a Samba binary
259 def SAMBA_BINARY(bld, binname, source_list,
272 ilist = '. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
273 ilist = bld.NORMPATH(ilist)
275 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
278 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, binname, deps)
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])
287 bld.SET_BUILD_GROUP(group)
289 features = 'cc cprogram',
290 source = source_list,
292 uselib_local = localdeps,
295 ccflags = CURRENT_CFLAGS(bld, cflags),
296 add_objects = add_objects,
298 # put a link to the binary in bin/
299 if not Options.is_install:
302 rule = 'rm -f %s && cp ${SRC} .' % (binname),
306 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
309 #################################################################
310 # define a Samba python module
311 def SAMBA_PYTHON(bld, name, source_list,
316 if not SET_TARGET_TYPE(bld, name, 'PYTHON'):
319 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, name, deps)
322 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
326 #################################################################
327 # define a Samba ASN1 target
328 def SAMBA_ASN1(bld, name, source,
331 if not SET_TARGET_TYPE(bld, name, 'ASN1'):
333 bld.SET_BUILD_GROUP('build_source')
338 asn1options = options,
339 asn1directory = directory
341 Build.BuildContext.SAMBA_ASN1 = SAMBA_ASN1
345 #################################################################
346 # define a Samba ET target
347 def SAMBA_ERRTABLE(bld, name, source,
350 if not SET_TARGET_TYPE(bld, name, 'ET'):
352 bld.SET_BUILD_GROUP('build_source')
358 Build.BuildContext.SAMBA_ERRTABLE = SAMBA_ERRTABLE
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)
366 if not SET_TARGET_TYPE(bld, name, 'PIDL'):
369 bld.SET_BUILD_GROUP('build_source')
376 Build.BuildContext.SAMBA_PIDL = SAMBA_PIDL
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
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')
394 source = source_list,
396 rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
398 Build.BuildContext.AUTOPROTO = AUTOPROTO
401 #################################################################
402 # define a Samba module.
403 def SAMBA_MODULE(bld, modname, source_list,
413 if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
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)
421 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
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')
428 source = source_list,
430 ccflags = CURRENT_CFLAGS(bld, cflags),
431 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist)
432 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
435 #################################################################
436 # define a Samba subsystem
437 def SAMBA_SUBSYSTEM(bld, modname, source_list,
446 init_function_sentinal=None):
448 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
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):
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)
461 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
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)
468 source = source_list,
470 ccflags = CURRENT_CFLAGS(bld, cflags),
471 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist)
472 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
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
484 debug("build: Processing subdirectory %s" % dir)
487 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
490 ##########################################################
491 # add a new top level command to waf
492 def ADD_COMMAND(opt, name, function):
493 Utils.g_module.__dict__[name] = function
495 Options.Handler.ADD_COMMAND = ADD_COMMAND
497 ###########################################################
498 # setup build groups used to ensure that the different build
499 # phases happen consecutively
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
512 ###########################################################
513 # set the current build group
514 def SET_BUILD_GROUP(bld, group):
515 if not 'USING_BUILD_GROUPS' in bld.env:
518 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP