# a waf tool to add autoconf-like macros to the configure section
# and for SAMBA_ macros for building libraries, binaries etc
-import Build
+import Build, os, Logs, sys, Configure, Options
from Configure import conf
+LIB_PATH="shared"
+
+######################################################
+# this is used as a decorator to make functions only
+# run once. Based on the idea from
+# http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
+runonce_ret = {}
+def runonce(function):
+ def wrapper(*args):
+ if args in runonce_ret:
+ return runonce_ret[args]
+ else:
+ ret = function(*args)
+ runonce_ret[args] = ret
+ return ret
+ return wrapper
+
####################################################
# some autoconf like helpers, to make the transition
# to waf a bit easier for those used to autoconf
# m4 files
+@runonce
@conf
def DEFUN(conf, d, v):
conf.define(d, v, quote=False)
conf.env.append_value('CCDEFINES', d + '=' + str(v))
+@runonce
+def CHECK_HEADER(conf, h):
+ if conf.check(header_name=h):
+ conf.env.hlist.append(h)
+
@conf
def CHECK_HEADERS(conf, list):
for hdr in list.split():
- if conf.check(header_name=hdr):
- conf.env.hlist.append(hdr)
+ CHECK_HEADER(conf, hdr)
@conf
def CHECK_TYPES(conf, list):
if not conf.check(type_name=t, header_name=conf.env.hlist):
conf.DEFUN(t, alternate)
+@runonce
+def CHECK_FUNC(conf, f):
+ conf.check(function_name=f, header_name=conf.env.hlist)
+
+
@conf
def CHECK_FUNCS(conf, list):
for f in list.split():
- conf.check(function_name=f, header_name=conf.env.hlist)
+ CHECK_FUNC(conf, f)
@conf
def CHECK_FUNCS_IN(conf, list, library):
if conf.check(lib=library, uselib_store=library):
for f in list.split():
conf.check(function_name=f, lib=library, header_name=conf.env.hlist)
+ conf.env['LIB_' + library.upper()] = library
#################################################
# write out config.h in the right directory
@conf
-def SAMBA_CONFIG_H(conf):
- import os
- if os.path.normpath(conf.curdir) == os.path.normpath(conf.srcdir):
- conf.write_config_header('config.h')
+def SAMBA_CONFIG_H(conf, path=None):
+ if os.path.normpath(conf.curdir) != os.path.normpath(os.environ.get('PWD')):
+ return
+ if path is None:
+ conf.write_config_header('config.h', top=True)
+ else:
+ conf.write_config_header(path)
##############################################################
conf.env[name] = conf.env['PREFIX'] + default
conf.define(name, conf.env[name], quote=True)
+##############################################################
+# add some CFLAGS to the command line
+@conf
+def ADD_CFLAGS(conf, flags):
+ conf.env.append_value('CCFLAGS', flags.split())
+
################################################################
# magic rpath handling
# Note that this should really check if rpath is available on this platform
# and it should also honor an --enable-rpath option
def set_rpath(bld):
- import Options
if Options.is_install:
- bld.env['RPATH'] = ['-Wl,-rpath=' + bld.env.PREFIX + '/lib']
+ if bld.env['RPATH_ON_INSTALL']:
+ bld.env['RPATH'] = ['-Wl,-rpath=%s/lib' % bld.env.PREFIX]
+ else:
+ bld.env['RPATH'] = []
else:
- bld.env.append_value('RPATH', '-Wl,-rpath=build/default')
+ rpath = os.path.normpath('%s/bin/%s' % (bld.curdir, LIB_PATH))
+ bld.env.append_value('RPATH', '-Wl,-rpath=%s' % rpath)
Build.BuildContext.set_rpath = set_rpath
+#############################################################
+# return a named build cache dictionary, used to store
+# state inside the following functions
+def BUILD_CACHE(bld, name):
+ if name in bld.env:
+ return bld.env[name]
+ bld.env[name] = {}
+ return bld.env[name]
+
+
+#############################################################
+# a build assert call
+def ASSERT(ctx, expression, msg):
+ if not expression:
+ sys.stderr.write("ERROR: %s\n" % msg)
+ raise AssertionError
+Build.BuildContext.ASSERT = ASSERT
+
################################################################
# create a list of files by pre-pending each with a subdir name
def SUBDIR(bld, subdir, list):
return ret
Build.BuildContext.SUBDIR = SUBDIR
+#################################################################
+# create the samba build environment
+@conf
+def SAMBA_BUILD_ENV(conf):
+ libpath="%s/%s" % (conf.blddir, LIB_PATH)
+ if not os.path.exists(libpath):
+ os.mkdir(libpath)
+
+##############################################
+# remove .. elements from a path list
+def NORMPATH(bld, ilist):
+ return " ".join([os.path.normpath(p) for p in ilist.split(" ")])
+Build.BuildContext.NORMPATH = NORMPATH
################################################################
-# this will contain the set of includes needed per Samba library
-Build.BuildContext.SAMBA_LIBRARY_INCLUDES = {}
+# add an init_function to the list for a subsystem
+def ADD_INIT_FUNCTION(bld, subsystem, init_function):
+ if init_function is None:
+ return
+ bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
+ cache = BUILD_CACHE(bld, 'INIT_FUNCTIONS')
+ if not subsystem in cache:
+ cache[subsystem] = ''
+ cache[subsystem] += '%s,' % init_function
+Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
+
+#######################################################
+# d1 += d2
+def dict_concat(d1, d2):
+ for t in d2:
+ if t not in d1:
+ d1[t] = d2[t]
################################################################
-# this will contain the library dependencies of each Samba library
-Build.BuildContext.SAMBA_LIBRARY_DEPS = {}
+# recursively build the dependency list for a target
+def FULL_DEPENDENCIES(bld, cache, target, chain, path):
+ if not target in cache:
+ return {}
+ deps = cache[target].copy()
+ for t in cache[target]:
+ bld.ASSERT(t not in chain, "Circular dependency for %s: %s->%s" % (t, path, t));
+ c2 = chain.copy()
+ c2[t] = True
+ dict_concat(deps, FULL_DEPENDENCIES(bld, cache, t, c2, "%s->%s" % (path, t)))
+ return deps
+
+############################################################
+# check our build dependencies for circular dependencies
+def CHECK_TARGET_DEPENDENCY(bld, target):
+ cache = BUILD_CACHE(bld, 'LIB_DEPS')
+ FULL_DEPENDENCIES(bld, cache, target, { target:True }, target)
+
+################################################################
+# add to the dependency list. Return a new dependency list with
+# any circular dependencies removed
+# returns a tuple containing (systemdeps, localdeps)
+def ADD_DEPENDENCIES(bld, name, deps):
+ cache = BUILD_CACHE(bld, 'LIB_DEPS')
+ if not name in cache:
+ cache[name] = {}
+ list = deps.split()
+ list2 = []
+ for d in list:
+ cache[name][d] = True;
+ try:
+ CHECK_TARGET_DEPENDENCY(bld, name)
+ list2.append(d)
+ except AssertionError:
+ print "Removing dependency %s from target %s" % (d, name)
+ del(cache[name][d])
+
+ # extract out the system dependencies
+ sysdeps = []
+ localdeps = []
+ cache = BUILD_CACHE(bld, 'EMPTY_LIBS')
+ for d in list2:
+ # strip out any dependencies on empty libraries
+ if d in cache:
+ continue
+ libname = 'LIB_%s' % d.upper()
+ if libname in bld.env:
+ sysdeps.append(d)
+ else:
+ localdeps.append(d)
+ return (' '.join(sysdeps), ' '.join(localdeps))
+
#################################################################
# return a include list for a set of library dependencies
-def SAMBA_LIBRARY_INCLUDE_LIST(bld, libdeps):
+def SAMBA_LIBRARY_INCLUDE_LIST(bld, deps):
ret = bld.curdir + ' '
- for l in libdeps.split():
- if l in bld.SAMBA_LIBRARY_INCLUDES:
- ret = ret + bld.SAMBA_LIBRARY_INCLUDES[l] + ' '
+ cache = BUILD_CACHE(bld, 'INCLUDE_LIST')
+ for l in deps.split():
+ if l in cache:
+ ret = ret + cache[l] + ' '
return ret
Build.BuildContext.SAMBA_LIBRARY_INCLUDE_LIST = SAMBA_LIBRARY_INCLUDE_LIST
-#################################################################
-# return a library list for a set of library dependencies
-def SAMBA_LIBRARY_LIB_LIST(bld, libdeps):
- ret = ' '
- for l in libdeps.split():
- if l in bld.SAMBA_LIBRARY_DEPS:
- ret = ret + l + ' ' + bld.SAMBA_LIBRARY_LIB_LIST(bld.SAMBA_LIBRARY_DEPS[l])
- return ret
-Build.BuildContext.SAMBA_LIBRARY_LIB_LIST = SAMBA_LIBRARY_LIB_LIST
-
-
#################################################################
# define a Samba library
def SAMBA_LIBRARY(bld, libname, source_list,
- libdeps='', include_list='.', vnum=None):
- ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(libdeps) + bld.SUBDIR(bld.curdir, include_list)
+ deps='',
+ public_deps='',
+ include_list='.',
+ public_headers=None,
+ vnum=None,
+ cflags=None,
+ autoproto=None):
+ # print "Declaring SAMBA_LIBRARY %s" % libname
+ #print "SAMBA_LIBRARY '%s' with deps '%s'" % (libname, deps)
+
+ # remember empty libraries, so we can strip the dependencies
+ if (source_list == '') or (source_list == []):
+ cache = BUILD_CACHE(bld, 'EMPTY_LIBS')
+ cache[libname] = True
+ return
+
+ (sysdeps, deps) = ADD_DEPENDENCIES(bld, libname, deps)
+
+ ilist = bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + bld.SUBDIR(bld.curdir, include_list)
+ ilist = bld.NORMPATH(ilist)
bld(
features = 'cc cshlib',
source = source_list,
target=libname,
- includes='. ' + ilist,
+ uselib_local = deps,
+ uselib = sysdeps,
+ includes='. ' + os.environ.get('PWD') + '/bin/default ' + ilist,
vnum=vnum)
- bld.SAMBA_LIBRARY_INCLUDES[libname] = ilist
- bld.SAMBA_LIBRARY_DEPS[libname] = libdeps
+
+ # put a link to the library in bin/shared
+ soext=""
+ if vnum is not None:
+ soext = '.' + vnum.split('.')[0]
+ bld(
+ source = 'lib%s.so' % libname,
+ target = '%s.lnk' % libname,
+ rule = 'ln -sf ../${SRC}%s %s/lib%s.so%s && touch ${TGT}' %
+ (soext, LIB_PATH, libname, soext),
+ shell = True
+ )
+ cache = BUILD_CACHE(bld, 'INCLUDE_LIST')
+ cache[libname] = ilist
+
Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
+
#################################################################
# define a Samba binary
-def SAMBA_BINARY(bld, binname, source_list, libdeps='', include_list=''):
+def SAMBA_BINARY(bld, binname, source_list,
+ deps='',
+ include_list='',
+ public_headers=None,
+ modules=None,
+ installdir=None,
+ ldflags=None,
+ cflags=None,
+ autoproto=None,
+ use_hostcc=None,
+ compiler=None,
+ manpages=None):
+ ilist = '. ' + os.environ.get('PWD') + '/bin/default ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(deps) + ' ' + include_list
+ ilist = bld.NORMPATH(ilist)
+ ccflags = ''
+
+ #print "SAMBA_BINARY '%s' with deps '%s'" % (binname, deps)
+
+ (sysdeps, deps) = ADD_DEPENDENCIES(bld, binname, deps)
+
+ cache = BUILD_CACHE(bld, 'INIT_FUNCTIONS')
+ if modules is not None:
+ for m in modules.split():
+ bld.ASSERT(m in cache,
+ "No init_function defined for module '%s' in binary '%s'" % (m, binname))
+ ccflags += ' -DSTATIC_%s_MODULES="%s"' % (m, cache[m])
+
bld(
features = 'cc cprogram',
source = source_list,
target = binname,
- uselib_local = bld.SAMBA_LIBRARY_LIB_LIST(libdeps),
- includes = '. ' + bld.SAMBA_LIBRARY_INCLUDE_LIST(libdeps) + include_list)
+ uselib_local = deps,
+ uselib = sysdeps,
+ includes = ilist,
+ ccflags = ccflags,
+ top=True)
+ # put a link to the binary in bin/
+ bld(
+ source = binname,
+ rule = 'ln -sf ${SRC} .',
+ )
Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
+
+#################################################################
+# define a Samba python module
+def SAMBA_PYTHON(bld, name, source_list,
+ deps='',
+ public_deps='',
+ realname=''):
+
+ #print "SAMBA_PYTHON '%s' with deps '%s'" % (name, deps)
+
+ (sysdeps, deps) = ADD_DEPENDENCIES(bld, name, deps)
+
+ Logs.debug('runner: PYTHON_SAMBA not implemented')
+ return
+Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
+
+
+################################################################
+# build a C prototype file automatically
+def AUTOPROTO(bld, header, source_list):
+ if header is not None:
+ bld(
+ source = source_list,
+ target = header,
+ rule = '../script/mkproto.pl --srcdir=.. --builddir=. --public=/dev/null --private=${TGT} ${SRC}'
+ )
+Build.BuildContext.AUTOPROTO = AUTOPROTO
+
+
+#################################################################
+# define a Samba module.
+def SAMBA_MODULE(bld, modname, source_list,
+ deps='',
+ include_list='.',
+ subsystem=None,
+ init_function=None,
+ autoproto=None,
+ aliases=None,
+ cflags=None,
+ output_type=None):
+ #print "SAMBA_MODULE '%s' with deps '%s'" % (modname, deps)
+ bld.ADD_INIT_FUNCTION(subsystem, init_function)
+ bld.AUTOPROTO(autoproto, source_list)
+ bld.SAMBA_LIBRARY(modname, source_list,
+ deps=deps, include_list=include_list)
+Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
+
+#################################################################
+# define a Samba subsystem
+def SAMBA_SUBSYSTEM(bld, modname, source_list,
+ deps='',
+ public_deps='',
+ include_list='.',
+ public_headers=None,
+ autoproto=None,
+ cflags=None,
+ init_function_sentinal=None):
+ bld.SAMBA_LIBRARY(modname, source_list,
+ deps=deps, include_list=include_list)
+Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
+
+
+###############################################################
+# add a new set of build rules from a subdirectory
+# the @runonce decorator ensures we don't end up
+# with duplicate rules
+@runonce
+def BUILD_SUBDIR(bld, dir):
+ bld.add_subdirs(dir)
+Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
+
+
############################################################
# this overrides the 'waf -v' debug output to be in a nice
# unix like format instead of a python list.
Build.BuildContext.exec_command = exec_command
-######################################################
-# this is used as a decorator to make functions only
-# run once. Based on the idea from
-# http://stackoverflow.com/questions/815110/is-there-a-decorator-to-simply-cache-function-return-values
-runonce_ret = {}
-def runonce(function):
- def wrapper(*args):
- if args in runonce_ret:
- return runonce_ret[args]
- else:
- ret = function(*args)
- runonce_ret[args] = ret
- return ret
- return wrapper