X-Git-Url: http://git.samba.org/samba.git/?p=nivanova%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=lib%2Freplace%2Fwafsamba.py;h=4cf8902de6d53e3b6d1ca0115181d3a373196f23;hp=f57ce284174c1f6ad37cb4486d9a6a4cf08f071c;hb=06940d57967039792d945a4999ccd31dfe4b83c4;hpb=45d23d1f5360046e7dc6d357a28bcf44db8207bc diff --git a/lib/replace/wafsamba.py b/lib/replace/wafsamba.py index f57ce284174..4cf8902de6d 100644 --- a/lib/replace/wafsamba.py +++ b/lib/replace/wafsamba.py @@ -1,24 +1,46 @@ # 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): @@ -35,24 +57,33 @@ def CHECK_TYPE(conf, t, alternate): 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) ############################################################## @@ -63,6 +94,12 @@ def CONFIG_PATH(conf, name, default): 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 @@ -71,14 +108,35 @@ def CONFIG_PATH(conf, name, default): # 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): @@ -88,62 +146,270 @@ 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. @@ -166,17 +432,3 @@ def exec_command(self, cmd, **kw): 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