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
5 from Configure import conf
9 ######################################################
10 # this is used as a decorator to make functions only
11 # run once. Based on the idea from
12 # http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
14 def runonce(function):
16 if args in runonce_ret:
17 return runonce_ret[args]
20 runonce_ret[args] = ret
25 ####################################################
26 # some autoconf like helpers, to make the transition
27 # to waf a bit easier for those used to autoconf
31 def DEFUN(conf, d, v):
32 conf.define(d, v, quote=False)
33 conf.env.append_value('CCDEFINES', d + '=' + str(v))
36 def CHECK_HEADER(conf, h):
37 if conf.check(header_name=h):
38 conf.env.hlist.append(h)
41 def CHECK_HEADERS(conf, list):
42 for hdr in list.split():
43 CHECK_HEADER(conf, hdr)
46 def CHECK_TYPES(conf, list):
47 for t in list.split():
48 conf.check(type_name=t, header_name=conf.env.hlist)
51 def CHECK_TYPE_IN(conf, t, hdr):
52 if conf.check(header_name=hdr):
53 conf.check(type_name=t, header_name=hdr)
56 def CHECK_TYPE(conf, t, alternate):
57 if not conf.check(type_name=t, header_name=conf.env.hlist):
58 conf.DEFUN(t, alternate)
61 def CHECK_FUNC(conf, f):
62 conf.check(function_name=f, header_name=conf.env.hlist)
66 def CHECK_FUNCS(conf, list):
67 for f in list.split():
71 def CHECK_FUNCS_IN(conf, list, library):
72 if conf.check(lib=library, uselib_store=library):
73 for f in list.split():
74 conf.check(function_name=f, lib=library, header_name=conf.env.hlist)
75 conf.env['LIB_' + library.upper()] = library
78 #################################################
79 # write out config.h in the right directory
81 def SAMBA_CONFIG_H(conf, path=None):
82 if os.path.normpath(conf.curdir) != os.path.normpath(os.environ.get('PWD')):
85 conf.write_config_header('config.h', top=True)
87 conf.write_config_header(path)
90 ##############################################################
91 # setup a configurable path
93 def CONFIG_PATH(conf, name, default):
94 if not name in conf.env:
95 conf.env[name] = conf.env['PREFIX'] + default
96 conf.define(name, conf.env[name], quote=True)
98 ##############################################################
99 # add some CFLAGS to the command line
101 def ADD_CFLAGS(conf, flags):
102 conf.env.append_value('CCFLAGS', flags.split())
105 ################################################################
106 # magic rpath handling
108 # we want a different rpath when installing and when building
109 # Note that this should really check if rpath is available on this platform
110 # and it should also honor an --enable-rpath option
112 if Options.is_install:
113 if bld.env['RPATH_ON_INSTALL']:
114 bld.env['RPATH'] = ['-Wl,-rpath=%s/lib' % bld.env.PREFIX]
116 bld.env['RPATH'] = []
118 rpath = os.path.normpath('%s/bin/%s' % (bld.curdir, LIB_PATH))
119 bld.env.append_value('RPATH', '-Wl,-rpath=%s' % rpath)
120 Build.BuildContext.set_rpath = set_rpath
123 #############################################################
124 # return a named build cache dictionary, used to store
125 # state inside the following functions
126 def BUILD_CACHE(bld, name):
133 #############################################################
134 # a build assert call
135 def ASSERT(ctx, expression, msg):
137 sys.stderr.write("ERROR: %s\n" % msg)
139 Build.BuildContext.ASSERT = ASSERT
141 ################################################################
142 # create a list of files by pre-pending each with a subdir name
143 def SUBDIR(bld, subdir, list):
145 for l in list.split():
146 ret = ret + subdir + '/' + l + ' '
148 Build.BuildContext.SUBDIR = SUBDIR
150 #################################################################
151 # create the samba build environment
153 def SAMBA_BUILD_ENV(conf):
154 libpath="%s/%s" % (conf.blddir, LIB_PATH)
155 if not os.path.exists(libpath):
158 ##############################################
159 # remove .. elements from a path list
160 def NORMPATH(bld, ilist):
161 return " ".join([os.path.normpath(p) for p in ilist.split(" ")])
162 Build.BuildContext.NORMPATH = NORMPATH
164 ################################################################
165 # add an init_function to the list for a subsystem
166 def ADD_INIT_FUNCTION(bld, subsystem, init_function):
167 if init_function is None:
169 bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
170 cache = BUILD_CACHE(bld, 'INIT_FUNCTIONS')
171 if not subsystem in cache:
172 cache[subsystem] = ''
173 cache[subsystem] += '%s,' % init_function
174 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
176 #######################################################
178 def dict_concat(d1, d2):
183 ################################################################
184 # recursively build the dependency list for a target
185 def FULL_DEPENDENCIES(bld, cache, target, chain, path):
186 if not target in cache:
188 deps = cache[target].copy()
189 for t in cache[target]:
190 bld.ASSERT(t not in chain, "Circular dependency for %s: %s->%s" % (t, path, t));
193 dict_concat(deps, FULL_DEPENDENCIES(bld, cache, t, c2, "%s->%s" % (path, t)))
196 ############################################################
197 # check our build dependencies for circular dependencies
198 def CHECK_TARGET_DEPENDENCY(bld, target):
199 cache = BUILD_CACHE(bld, 'LIB_DEPS')
200 FULL_DEPENDENCIES(bld, cache, target, { target:True }, target)
202 ################################################################
203 # add to the dependency list. Return a new dependency list with
204 # any circular dependencies removed
205 def ADD_DEPENDENCIES(bld, name, deps):
206 cache = BUILD_CACHE(bld, 'LIB_DEPS')
207 if not name in cache:
212 cache[name][d] = True;
214 CHECK_TARGET_DEPENDENCY(bld, name)
216 except AssertionError:
217 print "Removing dependency %s from target %s" % (d, name)
219 return ' '.join(list2)
222 #################################################################
223 # return a include list for a set of library dependencies
224 def SAMBA_LIBRARY_INCLUDE_LIST(bld, deps):
225 ret = bld.curdir + ' '
226 cache = BUILD_CACHE(bld, 'INCLUDE_LIST')
227 for l in deps.split():
229 ret = ret + cache[l] + ' '
231 Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
233 #################################################################
234 # define a Samba library
235 def SAMBA_LIBRARY(bld, libname, source_list,
243 # print "Declaring SAMBA_LIBRARY %s" % libname
244 #print "SAMBA_LIBRARY '%s' with deps '%s'" % (libname, deps)
246 deps = ADD_DEPENDENCIES(bld, libname, deps)
248 ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
249 ilist = bld.NORMPATH(ilist)
251 features = 'cc cshlib',
252 source = source_list,
255 includes='. ' + os.environ.get('PWD') + '/bin/default ' + ilist,
258 # put a link to the library in bin/shared
261 soext = '.' + vnum.split('.')[0]
263 source = 'lib%s.so' % libname,
264 target = '%s.lnk' % libname,
265 rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s && touch ${TGT}' %
266 (soext, LIB_PATH, libname, soext),
269 cache = BUILD_CACHE(bld, 'INCLUDE_LIST')
270 cache[libname] = ilist
272 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
275 #################################################################
276 # define a Samba binary
277 def SAMBA_BINARY(bld, binname, source_list,
288 ilist = '. ' + os.environ.get('PWD') + '/bin/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
289 ilist = bld.NORMPATH(ilist)
292 #print "SAMBA_BINARY '%s' with deps '%s'" % (binname, deps)
294 deps = ADD_DEPENDENCIES(bld, binname, deps)
296 cache = BUILD_CACHE(bld, 'INIT_FUNCTIONS')
297 if modules is not None:
298 for m in modules.split():
299 bld.ASSERT(m in cache,
300 "No init_function defined for module '%s' in binary '%s'" % (m, binname))
301 ccflags += ' -DSTATIC_%s_MODULES="%s"' % (m, cache[m])
304 features = 'cc cprogram',
305 source = source_list,
312 # put a link to the binary in bin/
315 rule = 'ln -sf ${SRC} .',
317 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
320 #################################################################
321 # define a Samba python module
322 def SAMBA_PYTHON(bld, name, source_list,
327 #print "SAMBA_PYTHON '%s' with deps '%s'" % (name, deps)
329 deps = ADD_DEPENDENCIES(bld, name, deps)
331 Logs.debug('runner: PYTHON_SAMBA not implemented')
333 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
336 ################################################################
337 # build a C prototype file automatically
338 def AUTOPROTO(bld, header, source_list):
339 if header is not None:
341 source = source_list,
343 rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
345 Build.BuildContext.AUTOPROTO = AUTOPROTO
348 #################################################################
349 # define a Samba module.
350 def SAMBA_MODULE(bld, modname, source_list,
359 #print "SAMBA_MODULE '%s' with deps '%s'" % (modname, deps)
360 bld.ADD_INIT_FUNCTION(subsystem, init_function)
361 bld.AUTOPROTO(autoproto, source_list)
362 bld.SAMBA_LIBRARY(modname, source_list,
363 deps=deps, include_list=include_list)
364 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
366 #################################################################
367 # define a Samba subsystem
368 def SAMBA_SUBSYSTEM(bld, modname, source_list,
375 init_function_sentinal=None):
376 bld.SAMBA_LIBRARY(modname, source_list,
377 deps=deps, include_list=include_list)
378 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
381 ###############################################################
382 # add a new set of build rules from a subdirectory
383 # the @runonce decorator ensures we don't end up
384 # with duplicate rules
386 def BUILD_SUBDIR(bld, dir):
388 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
391 ############################################################
392 # this overrides the 'waf -v' debug output to be in a nice
393 # unix like format instead of a python list.
394 # Thanks to ita on #waf for this
395 def exec_command(self, cmd, **kw):
398 if isinstance(cmd, list):
400 Logs.debug('runner: %s' % _cmd)
402 self.log.write('%s\n' % cmd)
405 if not kw.get('cwd', None):
407 except AttributeError:
408 self.cwd = kw['cwd'] = self.bldnode.abspath()
409 return Utils.exec_command(cmd, **kw)
410 Build.BuildContext.exec_command = exec_command