e1fae6211974589c709a0709e25137744b83c880
[nivanova/samba-autobuild/.git] / lib / replace / 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
5 from Configure import conf
6
7 LIB_PATH="shared"
8
9 ####################################################
10 # some autoconf like helpers, to make the transition
11 # to waf a bit easier for those used to autoconf
12 # m4 files
13 @conf
14 def DEFUN(conf, d, v):
15     conf.define(d, v, quote=False)
16     conf.env.append_value('CCDEFINES', d + '=' + str(v))
17
18 @conf
19 def CHECK_HEADERS(conf, list):
20     for hdr in list.split():
21         if conf.check(header_name=hdr):
22             conf.env.hlist.append(hdr)
23
24 @conf
25 def CHECK_TYPES(conf, list):
26     for t in list.split():
27         conf.check(type_name=t, header_name=conf.env.hlist)
28
29 @conf
30 def CHECK_TYPE_IN(conf, t, hdr):
31     if conf.check(header_name=hdr):
32         conf.check(type_name=t, header_name=hdr)
33
34 @conf
35 def CHECK_TYPE(conf, t, alternate):
36     if not conf.check(type_name=t, header_name=conf.env.hlist):
37         conf.DEFUN(t, alternate)
38
39 @conf
40 def CHECK_FUNCS(conf, list):
41     for f in list.split():
42         conf.check(function_name=f, header_name=conf.env.hlist)
43
44 @conf
45 def CHECK_FUNCS_IN(conf, list, library):
46     if conf.check(lib=library, uselib_store=library):
47         for f in list.split():
48             conf.check(function_name=f, lib=library, header_name=conf.env.hlist)
49         conf.env['LIB_' + library.upper()] = library
50
51 #################################################
52 # write out config.h in the right directory
53 @conf
54 def SAMBA_CONFIG_H(conf, path='config.h'):
55     if os.path.normpath(conf.curdir) == os.path.normpath(os.environ.get('PWD')):
56         conf.write_config_header(path, top=True)
57
58
59 ##############################################################
60 # setup a configurable path
61 @conf
62 def CONFIG_PATH(conf, name, default):
63     if not name in conf.env:
64         conf.env[name] = conf.env['PREFIX'] + default
65     conf.define(name, conf.env[name], quote=True)
66
67 ##############################################################
68 # add some CFLAGS to the command line
69 @conf
70 def ADD_CFLAGS(conf, flags):
71     conf.env.append_value('CCFLAGS', flags.split())
72
73
74 ################################################################
75 # magic rpath handling
76 #
77 # we want a different rpath when installing and when building
78 # Note that this should really check if rpath is available on this platform
79 # and it should also honor an --enable-rpath option
80 def set_rpath(bld):
81     import Options
82     if Options.is_install:
83         if bld.env['RPATH_ON_INSTALL']:
84             bld.env['RPATH'] = ['-Wl,-rpath=%s/lib' % bld.env.PREFIX]
85         else:
86             bld.env['RPATH'] = []
87     else:
88         rpath = os.path.normpath('%s/bin/%s' % (bld.curdir, LIB_PATH))
89         bld.env.append_value('RPATH', '-Wl,-rpath=%s' % rpath)
90 Build.BuildContext.set_rpath = set_rpath
91
92 #############################################################
93 # a build assert call
94 def ASSERT(ctx, expression, msg):
95     if not expression:
96         sys.stderr.write("ERROR: %s\n" % msg)
97         raise AssertionError
98 Build.BuildContext.ASSERT = ASSERT
99
100 ################################################################
101 # create a list of files by pre-pending each with a subdir name
102 def SUBDIR(bld, subdir, list):
103     ret = ''
104     for l in list.split():
105         ret = ret + subdir + '/' + l + ' '
106     return ret
107 Build.BuildContext.SUBDIR = SUBDIR
108
109 #################################################################
110 # create the samba build environment
111 @conf
112 def SAMBA_BUILD_ENV(conf):
113     libpath="%s/%s" % (conf.blddir, LIB_PATH)
114     if not os.path.exists(libpath):
115         os.mkdir(libpath)
116
117 ##############################################
118 # remove .. elements from a path list
119 def NORMPATH(bld, ilist):
120     return " ".join([os.path.normpath(p) for p in ilist.split(" ")])
121 Build.BuildContext.NORMPATH = NORMPATH
122
123 ################################################################
124 # this will contain the set of includes needed per Samba library
125 Build.BuildContext.SAMBA_LIBRARY_INCLUDES = {}
126
127 ################################################################
128 # init function list for a subsystem
129 Build.BuildContext.SAMBA_INIT_FUNCTIONS = {}
130
131 ################################################################
132 # add an init_function to the list for a subsystem
133 def ADD_INIT_FUNCTION(bld, subsystem, init_function):
134     if init_function is None:
135         return
136     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
137     if not subsystem in bld.SAMBA_INIT_FUNCTIONS:
138         bld.SAMBA_INIT_FUNCTIONS[subsystem] = ''
139     bld.SAMBA_INIT_FUNCTIONS[subsystem] += '%s,' % init_function
140 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
141
142
143 #################################################################
144 # return a include list for a set of library dependencies
145 def SAMBA_LIBRARY_INCLUDE_LIST(bld, deps):
146     ret = bld.curdir + ' '
147     for l in deps.split():
148         if l in bld.SAMBA_LIBRARY_INCLUDES:
149             ret = ret + bld.SAMBA_LIBRARY_INCLUDES[l] + ' '
150     return ret
151 Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
152
153 #################################################################
154 # define a Samba library
155 def SAMBA_LIBRARY(bld, libname, source_list,
156                   deps='',
157                   public_deps='',
158                   include_list='.',
159                   vnum=None,
160                   cflags=None):
161     ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
162     ilist = bld.NORMPATH(ilist)
163     bld(
164         features = 'cc cshlib',
165         source = source_list,
166         target=libname,
167         uselib_local = deps,
168         includes='. ' + os.environ.get('PWD') + '/bin/default ' + ilist,
169         vnum=vnum)
170
171     # put a link to the library in bin/shared
172     soext=""
173     if vnum is not None:
174         soext = '.' + vnum.split('.')[0]
175     bld(
176         source = 'lib%s.so' % libname,
177         target = '%s.lnk' % libname,
178         rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s && touch ${TGT}' %
179         (soext, LIB_PATH, libname, soext),
180         shell = True
181         )
182     bld.SAMBA_LIBRARY_INCLUDES[libname] = ilist
183 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
184
185
186 #################################################################
187 # define a Samba binary
188 def SAMBA_BINARY(bld, binname, source_list,
189                  deps='',
190                  syslibs='',
191                  include_list='',
192                  modules=None,
193                  installdir=None,
194                  ldflags=None,
195                  cflags=None):
196     ilist = '. ' + os.environ.get('PWD') + '/bin/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
197     ilist = bld.NORMPATH(ilist)
198     ccflags = ''
199
200     if modules is not None:
201         for m in modules.split():
202             bld.ASSERT(m in bld.SAMBA_INIT_FUNCTIONS,
203                        "No init_function defined for module '%s' in binary '%s'" % (m, binname))
204             modlist = bld.SAMBA_INIT_FUNCTIONS[m]
205             ccflags += ' -DSTATIC_%s_MODULES="%s"' % (m, modlist)
206
207     bld(
208         features = 'cc cprogram',
209         source = source_list,
210         target = binname,
211         uselib_local = deps,
212         uselib = syslibs,
213         includes = ilist,
214         ccflags = ccflags,
215         top=True)
216     # put a link to the binary in bin/
217     bld(
218         source = binname,
219         rule = 'ln -sf ${SRC} .',
220         )
221 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
222
223
224 #################################################################
225 # define a Samba python module
226 def SAMBA_PYTHON(bld, name, source_list,
227                  deps='',
228                  public_deps='',
229                  realname=''):
230     Logs.debug('runner: PYTHON_SAMBA not implemented')
231     return
232 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
233
234
235 ################################################################
236 # build a C prototype file automatically
237 def AUTOPROTO(bld, header, source_list):
238     if header is not None:
239         bld(
240             source = source_list,
241             target = header,
242             rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
243             )
244 Build.BuildContext.AUTOPROTO = AUTOPROTO
245
246
247 #################################################################
248 # define a Samba module.
249 def SAMBA_MODULE(bld, modname, source_list,
250                  deps='',
251                  include_list='.',
252                  subsystem=None,
253                  init_function=None,
254                  autoproto=None,
255                  aliases=None,
256                  cflags=None,
257                  output_type=None):
258     bld.ADD_INIT_FUNCTION(subsystem, init_function)
259     bld.AUTOPROTO(autoproto, source_list)
260     bld.SAMBA_LIBRARY(modname, source_list,
261                       deps=deps, include_list=include_list)
262 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
263
264 #################################################################
265 # define a Samba subsystem
266 def SAMBA_SUBSYSTEM(bld, modname, source_list,
267                     deps='',
268                     public_deps='',
269                     include_list='.',
270                     autoproto=None,
271                     cflags=None,
272                     init_function_sentinal=None):
273     bld.SAMBA_LIBRARY(modname, source_list,
274                       deps=deps, include_list=include_list)
275 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
276
277
278 ############################################################
279 # this overrides the 'waf -v' debug output to be in a nice
280 # unix like format instead of a python list.
281 # Thanks to ita on #waf for this
282 def exec_command(self, cmd, **kw):
283     import Utils, Logs
284     _cmd = cmd
285     if isinstance(cmd, list):
286         _cmd = ' '.join(cmd)
287     Logs.debug('runner: %s' % _cmd)
288     if self.log:
289         self.log.write('%s\n' % cmd)
290         kw['log'] = self.log
291     try:
292         if not kw.get('cwd', None):
293             kw['cwd'] = self.cwd
294     except AttributeError:
295         self.cwd = kw['cwd'] = self.bldnode.abspath()
296     return Utils.exec_command(cmd, **kw)
297 Build.BuildContext.exec_command = exec_command
298
299
300 ######################################################
301 # this is used as a decorator to make functions only
302 # run once. Based on the idea from
303 # http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
304 runonce_ret = {}
305 def runonce(function):
306     def wrapper(*args):
307         if args in runonce_ret:
308             return runonce_ret[args]
309         else:
310             ret = function(*args)
311             runonce_ret[args] = ret
312             return ret
313     return wrapper