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