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 *
13 from samba_pidl import *
18 #################################################################
19 # create the samba build environment
21 def SAMBA_BUILD_ENV(conf):
22 libpath="%s/%s" % (conf.blddir, LIB_PATH)
23 conf.env['BUILD_DIRECTORY'] = conf.blddir
24 if not os.path.exists(libpath):
27 ##############################################
28 # remove .. elements from a path list
29 def NORMPATH(bld, ilist):
30 return " ".join([os.path.normpath(p) for p in ilist.split(" ")])
31 Build.BuildContext.NORMPATH = NORMPATH
33 ################################################################
34 # add an init_function to the list for a subsystem
35 def ADD_INIT_FUNCTION(bld, subsystem, init_function):
36 if init_function is None:
38 bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
39 cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
40 if not subsystem in cache:
42 cache[subsystem] += '%s,' % init_function
43 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
45 ################################################################
46 # recursively build the dependency list for a target
47 def FULL_DEPENDENCIES(bld, cache, target, chain, path):
48 if not target in cache:
50 deps = cache[target].copy()
51 for t in cache[target]:
52 bld.ASSERT(t not in chain, "Circular dependency for %s: %s->%s" % (t, path, t));
55 dict_concat(deps, FULL_DEPENDENCIES(bld, cache, t, c2, "%s->%s" % (path, t)))
58 ############################################################
59 # check our build dependencies for circular dependencies
60 def CHECK_TARGET_DEPENDENCY(bld, target):
61 cache = LOCAL_CACHE(bld, 'LIB_DEPS')
62 return FULL_DEPENDENCIES(bld, cache, target, { target:True }, target)
64 ############################################################
65 # check that all dependencies have been declared
66 def CHECK_DEPENDENCIES(bld):
67 cache = LOCAL_CACHE(bld, 'LIB_DEPS')
68 target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
69 debug('deps: Checking dependencies')
71 deps = CHECK_TARGET_DEPENDENCY(bld, t)
73 #if not d in target_cache:
74 # print "Dependency '%s' of target '%s' not declared" % (d, t)
75 ASSERT(bld, d in target_cache,
76 "Dependency '%s' of target '%s' not declared" % (d, t))
77 debug("deps: Dependencies checked for %u targets" % len(target_cache))
78 Build.BuildContext.CHECK_DEPENDENCIES = CHECK_DEPENDENCIES
81 ############################################################
82 # pre-declare a target as being of a particular type
83 def PREDECLARE(bld, target, type):
84 cache = LOCAL_CACHE(bld, 'PREDECLARED_TARGET')
85 target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
86 ASSERT(bld, not target in target_cache, "Target '%s' is already declared" % target)
87 ASSERT(bld, not target in cache, "Target '%s' already predeclared" % target)
89 Build.BuildContext.PREDECLARE = PREDECLARE
93 ################################################################
94 # add to the dependency list. Return a new dependency list with
95 # any circular dependencies removed
96 # returns a tuple containing (systemdeps, localdeps, add_objects)
97 def ADD_DEPENDENCIES(bld, name, deps):
98 debug('deps: Calculating dependencies for %s' % name)
99 lib_deps = LOCAL_CACHE(bld, 'LIB_DEPS')
100 if not name in lib_deps:
105 lib_deps[name][d] = True;
107 CHECK_TARGET_DEPENDENCY(bld, name)
109 except AssertionError:
110 sys.stderr.write("Removing dependency %s from target %s" % (d, name))
111 del(lib_deps[name][d])
113 # extract out the system dependencies
117 cache = LOCAL_CACHE(bld, 'EMPTY_TARGETS')
118 target_cache = LOCAL_CACHE(bld, 'TARGET_TYPE')
119 predeclare = LOCAL_CACHE(bld, 'PREDECLARED_TARGET')
122 # strip out any dependencies on empty libraries
124 debug("deps: Removing empty dependency '%s' from '%s'" % (d, name))
128 if d in target_cache:
129 type = target_cache[d]
130 elif d in predeclare:
134 LOCAL_CACHE_SET(bld, 'ASSUMED_TARGET', d, type)
138 elif type == 'LIBRARY':
140 elif type == 'SUBSYSTEM':
141 add_objects.append(d)
143 elif type == 'MODULE':
144 add_objects.append(d)
146 elif type == 'PYTHON':
150 elif type == 'BINARY':
153 ASSERT(bld, False, "Unknown target type '%s' for dependency %s" % (
156 # for some types we have to build the list recursively
157 if recurse and (d in lib_deps):
158 rec_deps = ' '.join(lib_deps[d].keys())
159 (rec_sysdeps, rec_localdeps, rec_add_objects) = ADD_DEPENDENCIES(bld, d, rec_deps)
160 sysdeps.extend(rec_sysdeps.split())
161 localdeps.extend(rec_localdeps.split())
162 add_objects.extend(rec_add_objects.split())
164 debug('deps: Dependencies for %s: sysdeps: %u localdeps: %u add_objects=%u' % (
165 name, len(sysdeps), len(localdeps), len(add_objects)))
166 return (' '.join(sysdeps), ' '.join(localdeps), ' '.join(add_objects))
169 #################################################################
170 # return a include list for a set of library dependencies
171 def SAMBA_LIBRARY_INCLUDE_LIST(bld, deps):
172 ret = bld.curdir + ' '
173 cache = LOCAL_CACHE(bld, 'INCLUDE_LIST')
174 for l in deps.split():
176 ret = ret + cache[l] + ' '
178 Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
180 #################################################################
181 # define a Samba library
182 def SAMBA_LIBRARY(bld, libname, source,
192 if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'):
195 # remember empty libraries, so we can strip the dependencies
196 if (source == '') or (source == []):
197 LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', libname, True)
200 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, libname, deps)
202 ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
203 ilist = bld.NORMPATH(ilist)
204 bld.SET_BUILD_GROUP('main')
206 features = 'cc cshlib',
209 uselib_local = localdeps,
211 add_objects = add_objects,
212 ccflags = CURRENT_CFLAGS(bld, cflags),
213 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist,
216 # put a link to the library in bin/shared
219 soext = '.' + vnum.split('.')[0]
220 bld.SET_BUILD_GROUP('final')
222 source = 'lib%s.so' % libname,
223 rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s' %
224 (soext, LIB_PATH, libname, soext),
228 LOCAL_CACHE_SET(bld, 'INCLUDE_LIST', libname, ilist)
230 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
233 #################################################################
234 # define a Samba binary
235 def SAMBA_BINARY(bld, binname, source,
248 ilist = '. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
249 ilist = bld.NORMPATH(ilist)
251 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
254 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, binname, deps)
256 cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
257 if modules is not None:
258 for m in modules.split():
259 bld.ASSERT(m in cache,
260 "No init_function defined for module '%s' in binary '%s'" % (m, binname))
261 cflags += ' -DSTATIC_%s_MODULES="%s"' % (m, cache[m])
263 bld.SET_BUILD_GROUP(group)
265 features = 'cc cprogram',
268 uselib_local = localdeps,
271 ccflags = CURRENT_CFLAGS(bld, cflags),
272 add_objects = add_objects,
274 # put a link to the binary in bin/
275 if not Options.is_install:
278 rule = 'rm -f %s && cp ${SRC} .' % (binname),
282 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
285 #################################################################
286 # define a Samba python module
287 def SAMBA_PYTHON(bld, name, source,
292 if not SET_TARGET_TYPE(bld, name, 'PYTHON'):
295 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, name, deps)
298 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
302 #################################################################
303 # define a Samba ASN1 target
304 def SAMBA_ASN1(bld, name, source,
307 if not SET_TARGET_TYPE(bld, name, 'ASN1'):
309 bld.SET_BUILD_GROUP('build_source')
314 asn1options = options,
315 asn1directory = directory
317 Build.BuildContext.SAMBA_ASN1 = SAMBA_ASN1
321 #################################################################
322 # define a Samba ET target
323 def SAMBA_ERRTABLE(bld, name, source,
326 if not SET_TARGET_TYPE(bld, name, 'ET'):
328 bld.SET_BUILD_GROUP('build_source')
334 Build.BuildContext.SAMBA_ERRTABLE = SAMBA_ERRTABLE
339 #################################################################
340 # define a set of Samba PIDL targets
341 def SAMBA_PIDL_LIST(bld, directory, source, options=''):
342 for p in source.split():
343 bld.SAMBA_PIDL(directory, p, options)
344 Build.BuildContext.SAMBA_PIDL_LIST = SAMBA_PIDL_LIST
347 ################################################################
348 # build a C prototype file automatically
349 def AUTOPROTO(bld, header, source):
350 if header is not None:
351 bld.SET_BUILD_GROUP('prototypes')
355 rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
357 Build.BuildContext.AUTOPROTO = AUTOPROTO
360 #################################################################
361 # define a Samba module.
362 def SAMBA_MODULE(bld, modname, source,
372 if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
375 # remember empty modules, so we can strip the dependencies
376 if (source == '') or (source == []):
377 LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', modname, True)
380 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
382 ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
383 ilist = bld.NORMPATH(ilist)
384 bld.SET_BUILD_GROUP('main')
389 ccflags = CURRENT_CFLAGS(bld, cflags),
390 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist)
391 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
394 #################################################################
395 # define a Samba subsystem
396 def SAMBA_SUBSYSTEM(bld, modname, source,
405 init_function_sentinal=None):
407 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
410 # if the caller specifies a config_option, then we create a blank
411 # subsystem if that configuration option was found at configure time
412 if (config_option is not None) and bld.CONFIG_SET(config_option):
415 # remember empty subsystems, so we can strip the dependencies
416 if (source == '') or (source == []):
417 LOCAL_CACHE_SET(bld, 'EMPTY_TARGETS', modname, True)
420 (sysdeps, localdeps, add_objects) = ADD_DEPENDENCIES(bld, modname, deps)
422 ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
423 ilist = bld.NORMPATH(ilist)
424 bld.SET_BUILD_GROUP(group)
429 ccflags = CURRENT_CFLAGS(bld, cflags),
430 includes='. ' + bld.env['BUILD_DIRECTORY'] + '/default ' + ilist)
431 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
434 ###############################################################
435 # add a new set of build rules from a subdirectory
436 # the @runonce decorator ensures we don't end up
437 # with duplicate rules
438 def BUILD_SUBDIR(bld, dir):
439 path = os.path.normpath(bld.curdir + '/' + dir)
440 cache = LOCAL_CACHE(bld, 'SUBDIR_LIST')
441 if path in cache: return
443 debug("build: Processing subdirectory %s" % dir)
446 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
449 ##########################################################
450 # add a new top level command to waf
451 def ADD_COMMAND(opt, name, function):
452 Utils.g_module.__dict__[name] = function
454 Options.Handler.ADD_COMMAND = ADD_COMMAND
456 ###########################################################
457 # setup build groups used to ensure that the different build
458 # phases happen consecutively
460 def SETUP_BUILD_GROUPS(bld):
461 bld.env['USING_BUILD_GROUPS'] = True
462 bld.add_group('setup')
463 bld.add_group('build_compilers')
464 bld.add_group('build_source')
465 bld.add_group('prototypes')
466 bld.add_group('main')
467 bld.add_group('final')
468 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
471 ###########################################################
472 # set the current build group
473 def SET_BUILD_GROUP(bld, group):
474 if not 'USING_BUILD_GROUPS' in bld.env:
477 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP