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