build: recognise manpages keyword
[ira/wip.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                   autoproto=None):
166     ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
167     ilist = bld.NORMPATH(ilist)
168     bld(
169         features = 'cc cshlib',
170         source = source_list,
171         target=libname,
172         uselib_local = deps,
173         includes='. ' + os.environ.get('PWD') + '/bin/default ' + ilist,
174         vnum=vnum)
175
176     # put a link to the library in bin/shared
177     soext=""
178     if vnum is not None:
179         soext = '.' + vnum.split('.')[0]
180     bld(
181         source = 'lib%s.so' % libname,
182         target = '%s.lnk' % libname,
183         rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s && touch ${TGT}' %
184         (soext, LIB_PATH, libname, soext),
185         shell = True
186         )
187     bld.SAMBA_LIBRARY_INCLUDES[libname] = ilist
188 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
189
190
191 #################################################################
192 # define a Samba binary
193 def SAMBA_BINARY(bld, binname, source_list,
194                  deps='',
195                  syslibs='',
196                  include_list='',
197                  modules=None,
198                  installdir=None,
199                  ldflags=None,
200                  cflags=None,
201                  autoproto=None,
202                  manpages=None):
203     ilist = '. ' + os.environ.get('PWD') + '/bin/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
204     ilist = bld.NORMPATH(ilist)
205     ccflags = ''
206
207     if modules is not None:
208         for m in modules.split():
209             bld.ASSERT(m in bld.SAMBA_INIT_FUNCTIONS,
210                        "No init_function defined for module '%s' in binary '%s'" % (m, binname))
211             modlist = bld.SAMBA_INIT_FUNCTIONS[m]
212             ccflags += ' -DSTATIC_%s_MODULES="%s"' % (m, modlist)
213
214     bld(
215         features = 'cc cprogram',
216         source = source_list,
217         target = binname,
218         uselib_local = deps,
219         uselib = syslibs,
220         includes = ilist,
221         ccflags = ccflags,
222         top=True)
223     # put a link to the binary in bin/
224     bld(
225         source = binname,
226         rule = 'ln -sf ${SRC} .',
227         )
228 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
229
230
231 #################################################################
232 # define a Samba python module
233 def SAMBA_PYTHON(bld, name, source_list,
234                  deps='',
235                  public_deps='',
236                  realname=''):
237     Logs.debug('runner: PYTHON_SAMBA not implemented')
238     return
239 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
240
241
242 ################################################################
243 # build a C prototype file automatically
244 def AUTOPROTO(bld, header, source_list):
245     if header is not None:
246         bld(
247             source = source_list,
248             target = header,
249             rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
250             )
251 Build.BuildContext.AUTOPROTO = AUTOPROTO
252
253
254 #################################################################
255 # define a Samba module.
256 def SAMBA_MODULE(bld, modname, source_list,
257                  deps='',
258                  include_list='.',
259                  subsystem=None,
260                  init_function=None,
261                  autoproto=None,
262                  aliases=None,
263                  cflags=None,
264                  output_type=None):
265     bld.ADD_INIT_FUNCTION(subsystem, init_function)
266     bld.AUTOPROTO(autoproto, source_list)
267     bld.SAMBA_LIBRARY(modname, source_list,
268                       deps=deps, include_list=include_list)
269 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
270
271 #################################################################
272 # define a Samba subsystem
273 def SAMBA_SUBSYSTEM(bld, modname, source_list,
274                     deps='',
275                     public_deps='',
276                     include_list='.',
277                     autoproto=None,
278                     cflags=None,
279                     init_function_sentinal=None):
280     bld.SAMBA_LIBRARY(modname, source_list,
281                       deps=deps, include_list=include_list)
282 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
283
284
285 ############################################################
286 # this overrides the 'waf -v' debug output to be in a nice
287 # unix like format instead of a python list.
288 # Thanks to ita on #waf for this
289 def exec_command(self, cmd, **kw):
290     import Utils, Logs
291     _cmd = cmd
292     if isinstance(cmd, list):
293         _cmd = ' '.join(cmd)
294     Logs.debug('runner: %s' % _cmd)
295     if self.log:
296         self.log.write('%s\n' % cmd)
297         kw['log'] = self.log
298     try:
299         if not kw.get('cwd', None):
300             kw['cwd'] = self.cwd
301     except AttributeError:
302         self.cwd = kw['cwd'] = self.bldnode.abspath()
303     return Utils.exec_command(cmd, **kw)
304 Build.BuildContext.exec_command = exec_command
305
306
307 ######################################################
308 # this is used as a decorator to make functions only
309 # run once. Based on the idea from
310 # http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
311 runonce_ret = {}
312 def runonce(function):
313     def wrapper(*args):
314         if args in runonce_ret:
315             return runonce_ret[args]
316         else:
317             ret = function(*args)
318             runonce_ret[args] = ret
319             return ret
320     return wrapper