buildtools/wafsamba: add_manual_dependency needs bytes for value
[samba.git] / buildtools / wafsamba / wafsamba.py
index caa6fb128d6dfb3ae4e49f9f6d58c389af3f116a..59a4eacb305bc2f92e4639f5165bd5c0bb8e505c 100644 (file)
@@ -1,14 +1,14 @@
 # a waf tool to add autoconf-like macros to the configure section
 # and for SAMBA_ macros for building libraries, binaries etc
 
 # a waf tool to add autoconf-like macros to the configure section
 # and for SAMBA_ macros for building libraries, binaries etc
 
-import Build, os, sys, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs, Constants
-from Configure import conf
-from Logs import debug
+import os, sys, re, shutil, fnmatch
+from waflib import Build, Options, Task, Utils, TaskGen, Logs, Context, Errors
+from waflib.Configure import conf
+from waflib.Logs import debug
 from samba_utils import SUBST_VARS_RECURSIVE
 TaskGen.task_gen.apply_verif = Utils.nada
 
 # bring in the other samba modules
 from samba_utils import SUBST_VARS_RECURSIVE
 TaskGen.task_gen.apply_verif = Utils.nada
 
 # bring in the other samba modules
-from samba_optimisation import *
 from samba_utils import *
 from samba_version import *
 from samba_autoconf import *
 from samba_utils import *
 from samba_version import *
 from samba_autoconf import *
@@ -16,22 +16,22 @@ from samba_patterns import *
 from samba_pidl import *
 from samba_autoproto import *
 from samba_python import *
 from samba_pidl import *
 from samba_autoproto import *
 from samba_python import *
+from samba_perl import *
 from samba_deps import *
 from samba_bundled import *
 from samba_deps import *
 from samba_bundled import *
+from samba_third_party import *
+import samba_cross
 import samba_install
 import samba_conftests
 import samba_abi
 import samba_headers
 import samba_install
 import samba_conftests
 import samba_abi
 import samba_headers
-import tru64cc
-import irixcc
-import hpuxcc
 import generic_cc
 import samba_dist
 import samba_wildcard
 import generic_cc
 import samba_dist
 import samba_wildcard
-import stale_files
 import symbols
 import pkgconfig
 import configure_file
 import symbols
 import pkgconfig
 import configure_file
+import samba_waf18
 
 # some systems have broken threading in python
 if os.environ.get('WAF_NOTHREADS') == '1':
 
 # some systems have broken threading in python
 if os.environ.get('WAF_NOTHREADS') == '1':
@@ -41,8 +41,7 @@ LIB_PATH="shared"
 
 os.environ['PYTHONUNBUFFERED'] = '1'
 
 
 os.environ['PYTHONUNBUFFERED'] = '1'
 
-
-if Constants.HEXVERSION < 0x105019:
+if Context.HEXVERSION not in (0x2000800,):
     Logs.error('''
 Please use the version of waf that comes with Samba, not
 a system installed version. See http://wiki.samba.org/index.php/Waf
     Logs.error('''
 Please use the version of waf that comes with Samba, not
 a system installed version. See http://wiki.samba.org/index.php/Waf
@@ -52,26 +51,25 @@ Alternatively, please run ./configure and make as usual. That will
 call the right version of waf.''')
     sys.exit(1)
 
 call the right version of waf.''')
     sys.exit(1)
 
-
 @conf
 def SAMBA_BUILD_ENV(conf):
     '''create the samba build environment'''
 @conf
 def SAMBA_BUILD_ENV(conf):
     '''create the samba build environment'''
-    conf.env.BUILD_DIRECTORY = conf.blddir
-    mkdir_p(os.path.join(conf.blddir, LIB_PATH))
-    mkdir_p(os.path.join(conf.blddir, LIB_PATH, "private"))
-    mkdir_p(os.path.join(conf.blddir, "modules"))
-    mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
+    conf.env.BUILD_DIRECTORY = conf.bldnode.abspath()
+    mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH))
+    mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH, "private"))
+    mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, "modules"))
+    mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'python/samba/dcerpc'))
     # this allows all of the bin/shared and bin/python targets
     # to be expressed in terms of build directory paths
     # this allows all of the bin/shared and bin/python targets
     # to be expressed in terms of build directory paths
-    mkdir_p(os.path.join(conf.blddir, 'default'))
-    for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('python', 'python_modules')]:
-        link_target = os.path.join(conf.blddir, 'default/' + target)
+    mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'default'))
+    for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('python', 'python')]:
+        link_target = os.path.join(conf.env.BUILD_DIRECTORY, 'default/' + target)
         if not os.path.lexists(link_target):
             os.symlink('../' + source, link_target)
 
     # get perl to put the blib files in the build directory
         if not os.path.lexists(link_target):
             os.symlink('../' + source, link_target)
 
     # get perl to put the blib files in the build directory
-    blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
-    blib_src = os.path.join(conf.srcdir, 'pidl/blib')
+    blib_bld = os.path.join(conf.env.BUILD_DIRECTORY, 'default/pidl/blib')
+    blib_src = os.path.join(conf.srcnode.abspath(), 'pidl/blib')
     mkdir_p(blib_bld + '/man1')
     mkdir_p(blib_bld + '/man3')
     if os.path.islink(blib_src):
     mkdir_p(blib_bld + '/man1')
     mkdir_p(blib_bld + '/man3')
     if os.path.islink(blib_src):
@@ -92,6 +90,9 @@ def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
 
 
 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
 
 
+def generate_empty_file(task):
+    task.outputs[0].write('')
+    return 0
 
 #################################################################
 def SAMBA_LIBRARY(bld, libname, source,
 
 #################################################################
 def SAMBA_LIBRARY(bld, libname, source,
@@ -100,14 +101,17 @@ def SAMBA_LIBRARY(bld, libname, source,
                   includes='',
                   public_headers=None,
                   public_headers_install=True,
                   includes='',
                   public_headers=None,
                   public_headers_install=True,
+                  private_headers=None,
                   header_path=None,
                   pc_files=None,
                   vnum=None,
                   soname=None,
                   cflags='',
                   header_path=None,
                   pc_files=None,
                   vnum=None,
                   soname=None,
                   cflags='',
+                  cflags_end=None,
                   ldflags='',
                   external_library=False,
                   realname=None,
                   ldflags='',
                   external_library=False,
                   realname=None,
+                  keep_underscore=False,
                   autoproto=None,
                   autoproto_extra_source='',
                   group='main',
                   autoproto=None,
                   autoproto_extra_source='',
                   group='main',
@@ -121,7 +125,8 @@ def SAMBA_LIBRARY(bld, libname, source,
                   pyembed=False,
                   pyext=False,
                   target_type='LIBRARY',
                   pyembed=False,
                   pyext=False,
                   target_type='LIBRARY',
-                  bundled_extension=True,
+                  bundled_extension=False,
+                  bundled_name=None,
                   link_name=None,
                   abi_directory=None,
                   abi_match=None,
                   link_name=None,
                   abi_directory=None,
                   abi_match=None,
@@ -130,11 +135,19 @@ def SAMBA_LIBRARY(bld, libname, source,
                   private_library=False,
                   grouping_library=False,
                   allow_undefined_symbols=False,
                   private_library=False,
                   grouping_library=False,
                   allow_undefined_symbols=False,
+                  allow_warnings=False,
                   enabled=True):
     '''define a Samba library'''
 
                   enabled=True):
     '''define a Samba library'''
 
+    if pyembed and bld.env['IS_EXTRA_PYTHON']:
+        public_headers = None
+
+    if private_library and public_headers:
+        raise Errors.WafError("private library '%s' must not have public header files" %
+                             libname)
+
     if LIB_MUST_BE_PRIVATE(bld, libname):
     if LIB_MUST_BE_PRIVATE(bld, libname):
-        private_library=True
+        private_library = True
 
     if not enabled:
         SET_TARGET_TYPE(bld, libname, 'DISABLED')
 
     if not enabled:
         SET_TARGET_TYPE(bld, libname, 'DISABLED')
@@ -145,9 +158,15 @@ def SAMBA_LIBRARY(bld, libname, source,
         source = bld.SUBDIR(subdir, source)
 
     # remember empty libraries, so we can strip the dependencies
         source = bld.SUBDIR(subdir, source)
 
     # remember empty libraries, so we can strip the dependencies
-    if ((source == '') or (source == [])) and deps == '' and public_deps == '':
-        SET_TARGET_TYPE(bld, libname, 'EMPTY')
-        return
+    if ((source == '') or (source == [])):
+        if deps == '' and public_deps == '':
+            SET_TARGET_TYPE(bld, libname, 'EMPTY')
+            return
+        empty_c = libname + '.empty.c'
+        bld.SAMBA_GENERATOR('%s_empty_c' % libname,
+                            rule=generate_empty_file,
+                            target=empty_c)
+        source=empty_c
 
     if BUILTIN_LIBRARY(bld, libname):
         obj_target = libname
 
     if BUILTIN_LIBRARY(bld, libname):
         obj_target = libname
@@ -169,13 +188,16 @@ def SAMBA_LIBRARY(bld, libname, source,
                         includes       = includes,
                         public_headers = public_headers,
                         public_headers_install = public_headers_install,
                         includes       = includes,
                         public_headers = public_headers,
                         public_headers_install = public_headers_install,
+                        private_headers= private_headers,
                         header_path    = header_path,
                         cflags         = cflags,
                         header_path    = header_path,
                         cflags         = cflags,
+                        cflags_end     = cflags_end,
                         group          = subsystem_group,
                         autoproto      = autoproto,
                         autoproto_extra_source=autoproto_extra_source,
                         depends_on     = depends_on,
                         hide_symbols   = hide_symbols,
                         group          = subsystem_group,
                         autoproto      = autoproto,
                         autoproto_extra_source=autoproto_extra_source,
                         depends_on     = depends_on,
                         hide_symbols   = hide_symbols,
+                        allow_warnings = allow_warnings,
                         pyembed        = pyembed,
                         pyext          = pyext,
                         local_include  = local_include,
                         pyembed        = pyembed,
                         pyext          = pyext,
                         local_include  = local_include,
@@ -198,24 +220,34 @@ def SAMBA_LIBRARY(bld, libname, source,
     # we don't want any public libraries without version numbers
     if (not private_library and target_type != 'PYTHON' and not realname):
         if vnum is None and soname is None:
     # we don't want any public libraries without version numbers
     if (not private_library and target_type != 'PYTHON' and not realname):
         if vnum is None and soname is None:
-            raise Utils.WafError("public library '%s' must have a vnum" %
+            raise Errors.WafError("public library '%s' must have a vnum" %
                     libname)
         if pc_files is None:
                     libname)
         if pc_files is None:
-            raise Utils.WafError("public library '%s' must have pkg-config file" %
+            raise Errors.WafError("public library '%s' must have pkg-config file" %
                        libname)
                        libname)
-        if public_headers is None:
-            raise Utils.WafError("public library '%s' must have header files" %
+        if public_headers is None and not bld.env['IS_EXTRA_PYTHON']:
+            raise Errors.WafError("public library '%s' must have header files" %
                        libname)
 
                        libname)
 
-    if target_type == 'PYTHON' or realname or not private_library:
-        bundled_name = libname.replace('_', '-')
+    if bundled_name is not None:
+        pass
+    elif target_type == 'PYTHON' or realname or not private_library:
+        if keep_underscore:
+            bundled_name = libname
+        else:
+            bundled_name = libname.replace('_', '-')
     else:
     else:
-        bundled_name = PRIVATE_NAME(bld, libname, bundled_extension,
-            private_library)
+        assert (private_library == True and realname is None)
+        if abi_directory or vnum or soname:
+            bundled_extension=True
+        bundled_name = PRIVATE_NAME(bld, libname.replace('_', '-'),
+                                    bundled_extension, private_library)
 
     ldflags = TO_LIST(ldflags)
 
     ldflags = TO_LIST(ldflags)
+    if bld.env['ENABLE_RELRO'] is True:
+        ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now'))
 
 
-    features = 'cc cshlib symlink_lib install_lib'
+    features = 'c cshlib symlink_lib install_lib'
     if pyext:
         features += ' pyext'
     if pyembed:
     if pyext:
         features += ' pyext'
     if pyembed:
@@ -224,29 +256,38 @@ def SAMBA_LIBRARY(bld, libname, source,
     if abi_directory:
         features += ' abi_check'
 
     if abi_directory:
         features += ' abi_check'
 
+    if pyembed and bld.env['PYTHON_SO_ABI_FLAG']:
+        # For ABI checking, we don't care about the exact Python version.
+        # Replace the Python ABI tag (e.g. ".cpython-35m") by a generic ".py3"
+        abi_flag = bld.env['PYTHON_SO_ABI_FLAG']
+        replacement = '.py%s' % bld.env['PYTHON_VERSION'].split('.')[0]
+        version_libname = libname.replace(abi_flag, replacement)
+    else:
+        version_libname = libname
+
     vscript = None
     if bld.env.HAVE_LD_VERSION_SCRIPT:
         if private_library:
     vscript = None
     if bld.env.HAVE_LD_VERSION_SCRIPT:
         if private_library:
-            version = "%s_%s" % (Utils.g_module.APPNAME, Utils.g_module.VERSION)
+            version = "%s_%s" % (Context.g_module.APPNAME, Context.g_module.VERSION)
         elif vnum:
             version = "%s_%s" % (libname, vnum)
         else:
             version = None
         if version:
             vscript = "%s.vscript" % libname
         elif vnum:
             version = "%s_%s" % (libname, vnum)
         else:
             version = None
         if version:
             vscript = "%s.vscript" % libname
-            bld.ABI_VSCRIPT(libname, abi_directory, version, vscript,
+            bld.ABI_VSCRIPT(version_libname, abi_directory, version, vscript,
                             abi_match)
                             abi_match)
-            fullname = apply_pattern(bundled_name, bld.env.shlib_PATTERN)
+            fullname = apply_pattern(bundled_name, bld.env.cshlib_PATTERN)
             fullpath = bld.path.find_or_declare(fullname)
             vscriptpath = bld.path.find_or_declare(vscript)
             if not fullpath:
             fullpath = bld.path.find_or_declare(fullname)
             vscriptpath = bld.path.find_or_declare(vscript)
             if not fullpath:
-                raise Utils.WafError("unable to find fullpath for %s" % fullname)
+                raise Errors.WafError("unable to find fullpath for %s" % fullname)
             if not vscriptpath:
             if not vscriptpath:
-                raise Utils.WafError("unable to find vscript path for %s" % vscript)
+                raise Errors.WafError("unable to find vscript path for %s" % vscript)
             bld.add_manual_dependency(fullpath, vscriptpath)
             bld.add_manual_dependency(fullpath, vscriptpath)
-            if Options.is_install:
+            if bld.is_install:
                 # also make the .inst file depend on the vscript
                 # also make the .inst file depend on the vscript
-                instname = apply_pattern(bundled_name + '.inst', bld.env.shlib_PATTERN)
+                instname = apply_pattern(bundled_name + '.inst', bld.env.cshlib_PATTERN)
                 bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript))
             vscript = os.path.join(bld.path.abspath(bld.env), vscript)
 
                 bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript))
             vscript = os.path.join(bld.path.abspath(bld.env), vscript)
 
@@ -260,6 +301,7 @@ def SAMBA_LIBRARY(bld, libname, source,
         samba_deps      = deps,
         samba_includes  = includes,
         version_script  = vscript,
         samba_deps      = deps,
         samba_includes  = includes,
         version_script  = vscript,
+        version_libname = version_libname,
         local_include   = local_include,
         global_include  = global_include,
         vnum            = vnum,
         local_include   = local_include,
         global_include  = global_include,
         vnum            = vnum,
@@ -280,10 +322,15 @@ def SAMBA_LIBRARY(bld, libname, source,
         link_name = 'shared/%s' % realname
 
     if link_name:
         link_name = 'shared/%s' % realname
 
     if link_name:
+        if 'waflib.extras.compat15' in sys.modules:
+            link_name = 'default/' + link_name
         t.link_name = link_name
 
     if pc_files is not None and not private_library:
         t.link_name = link_name
 
     if pc_files is not None and not private_library:
-        bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
+        if pyembed and bld.env['IS_EXTRA_PYTHON']:
+            bld.PKG_CONFIG_FILES(pc_files, vnum=vnum, extra_name=bld.env['PYTHON_SO_ABI_FLAG'])
+        else:
+            bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
 
     if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and
         bld.env['XSLTPROC_MANPAGES']):
 
     if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and
         bld.env['XSLTPROC_MANPAGES']):
@@ -298,10 +345,12 @@ def SAMBA_BINARY(bld, binname, source,
                  deps='',
                  includes='',
                  public_headers=None,
                  deps='',
                  includes='',
                  public_headers=None,
+                 private_headers=None,
                  header_path=None,
                  modules=None,
                  ldflags=None,
                  cflags='',
                  header_path=None,
                  modules=None,
                  ldflags=None,
                  cflags='',
+                 cflags_end=None,
                  autoproto=None,
                  use_hostcc=False,
                  use_global_deps=True,
                  autoproto=None,
                  use_hostcc=False,
                  use_global_deps=True,
@@ -326,7 +375,7 @@ def SAMBA_BINARY(bld, binname, source,
     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
         return
 
     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
         return
 
-    features = 'cc cprogram symlink_bin install_bin'
+    features = 'c cprogram symlink_bin install_bin'
     if pyembed:
         features += ' pyembed'
 
     if pyembed:
         features += ' pyembed'
 
@@ -345,10 +394,10 @@ def SAMBA_BINARY(bld, binname, source,
     # only specify PIE flags for binaries
     pie_cflags = cflags
     pie_ldflags = TO_LIST(ldflags)
     # only specify PIE flags for binaries
     pie_cflags = cflags
     pie_ldflags = TO_LIST(ldflags)
-    if bld.env['ENABLE_PIE'] == True:
+    if bld.env['ENABLE_PIE'] is True:
         pie_cflags += ' -fPIE'
         pie_ldflags.extend(TO_LIST('-pie'))
         pie_cflags += ' -fPIE'
         pie_ldflags.extend(TO_LIST('-pie'))
-    if bld.env['ENABLE_RELRO'] == True:
+    if bld.env['ENABLE_RELRO'] is True:
         pie_ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now'))
 
     # first create a target for building the object files for this binary
         pie_ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now'))
 
     # first create a target for building the object files for this binary
@@ -359,6 +408,7 @@ def SAMBA_BINARY(bld, binname, source,
                         deps           = deps,
                         includes       = includes,
                         cflags         = pie_cflags,
                         deps           = deps,
                         includes       = includes,
                         cflags         = pie_cflags,
+                        cflags_end     = cflags_end,
                         group          = subsystem_group,
                         autoproto      = autoproto,
                         subsystem_name = subsystem_name,
                         group          = subsystem_group,
                         autoproto      = autoproto,
                         subsystem_name = subsystem_name,
@@ -407,6 +457,7 @@ def SAMBA_MODULE(bld, modname, source,
                  autoproto=None,
                  autoproto_extra_source='',
                  cflags='',
                  autoproto=None,
                  autoproto_extra_source='',
                  cflags='',
+                 cflags_end=None,
                  internal_module=True,
                  local_include=True,
                  global_include=True,
                  internal_module=True,
                  local_include=True,
                  global_include=True,
@@ -415,17 +466,21 @@ def SAMBA_MODULE(bld, modname, source,
                  enabled=True,
                  pyembed=False,
                  manpages=None,
                  enabled=True,
                  pyembed=False,
                  manpages=None,
-                 allow_undefined_symbols=False
+                 allow_undefined_symbols=False,
+                 allow_warnings=False,
+                 install=True
                  ):
     '''define a Samba module.'''
 
                  ):
     '''define a Samba module.'''
 
+    bld.ASSERT(subsystem, "You must specify a subsystem for SAMBA_MODULE(%s)" % modname)
+
     source = bld.EXPAND_VARIABLES(source, vars=vars)
     if subdir:
         source = bld.SUBDIR(subdir, source)
 
     if internal_module or BUILTIN_LIBRARY(bld, modname):
         # Do not create modules for disabled subsystems
     source = bld.EXPAND_VARIABLES(source, vars=vars)
     if subdir:
         source = bld.SUBDIR(subdir, source)
 
     if internal_module or BUILTIN_LIBRARY(bld, modname):
         # Do not create modules for disabled subsystems
-        if subsystem and GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
+        if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
             return
         bld.SAMBA_SUBSYSTEM(modname, source,
                     deps=deps,
             return
         bld.SAMBA_SUBSYSTEM(modname, source,
                     deps=deps,
@@ -433,8 +488,10 @@ def SAMBA_MODULE(bld, modname, source,
                     autoproto=autoproto,
                     autoproto_extra_source=autoproto_extra_source,
                     cflags=cflags,
                     autoproto=autoproto,
                     autoproto_extra_source=autoproto_extra_source,
                     cflags=cflags,
+                    cflags_end=cflags_end,
                     local_include=local_include,
                     global_include=global_include,
                     local_include=local_include,
                     global_include=global_include,
+                    allow_warnings=allow_warnings,
                     enabled=enabled)
 
         bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
                     enabled=enabled)
 
         bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
@@ -445,18 +502,17 @@ def SAMBA_MODULE(bld, modname, source,
         return
 
     # Do not create modules for disabled subsystems
         return
 
     # Do not create modules for disabled subsystems
-    if subsystem and GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
+    if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
         return
 
         return
 
-    obj_target = modname + '.objlist'
-
     realname = modname
     realname = modname
-    if subsystem is not None:
-        deps += ' ' + subsystem
-        while realname.startswith("lib"+subsystem+"_"):
-            realname = realname[len("lib"+subsystem+"_"):]
-        while realname.startswith(subsystem+"_"):
-            realname = realname[len(subsystem+"_"):]
+    deps += ' ' + subsystem
+    while realname.startswith("lib"+subsystem+"_"):
+        realname = realname[len("lib"+subsystem+"_"):]
+    while realname.startswith(subsystem+"_"):
+        realname = realname[len(subsystem+"_"):]
+
+    build_name = "%s_module_%s" % (subsystem, realname)
 
     realname = bld.make_libname(realname)
     while realname.startswith("lib"):
 
     realname = bld.make_libname(realname)
     while realname.startswith("lib"):
@@ -472,16 +528,20 @@ def SAMBA_MODULE(bld, modname, source,
                       deps=deps,
                       includes=includes,
                       cflags=cflags,
                       deps=deps,
                       includes=includes,
                       cflags=cflags,
+                      cflags_end=cflags_end,
                       realname = realname,
                       autoproto = autoproto,
                       local_include=local_include,
                       global_include=global_include,
                       vars=vars,
                       realname = realname,
                       autoproto = autoproto,
                       local_include=local_include,
                       global_include=global_include,
                       vars=vars,
+                      bundled_name=build_name,
                       link_name=build_link_name,
                       install_path="${MODULESDIR}/%s" % subsystem,
                       pyembed=pyembed,
                       manpages=manpages,
                       link_name=build_link_name,
                       install_path="${MODULESDIR}/%s" % subsystem,
                       pyembed=pyembed,
                       manpages=manpages,
-                      allow_undefined_symbols=allow_undefined_symbols
+                      allow_undefined_symbols=allow_undefined_symbols,
+                      allow_warnings=allow_warnings,
+                      install=install
                       )
 
 
                       )
 
 
@@ -495,6 +555,7 @@ def SAMBA_SUBSYSTEM(bld, modname, source,
                     includes='',
                     public_headers=None,
                     public_headers_install=True,
                     includes='',
                     public_headers=None,
                     public_headers_install=True,
+                    private_headers=None,
                     header_path=None,
                     cflags='',
                     cflags_end=None,
                     header_path=None,
                     cflags='',
                     cflags_end=None,
@@ -513,6 +574,7 @@ def SAMBA_SUBSYSTEM(bld, modname, source,
                     vars=None,
                     subdir=None,
                     hide_symbols=False,
                     vars=None,
                     subdir=None,
                     hide_symbols=False,
+                    allow_warnings=False,
                     pyext=False,
                     pyembed=False):
     '''define a Samba subsystem'''
                     pyext=False,
                     pyembed=False):
     '''define a Samba subsystem'''
@@ -522,9 +584,15 @@ def SAMBA_SUBSYSTEM(bld, modname, source,
         return
 
     # remember empty subsystems, so we can strip the dependencies
         return
 
     # remember empty subsystems, so we can strip the dependencies
-    if ((source == '') or (source == [])) and deps == '' and public_deps == '':
-        SET_TARGET_TYPE(bld, modname, 'EMPTY')
-        return
+    if ((source == '') or (source == [])):
+        if deps == '' and public_deps == '':
+            SET_TARGET_TYPE(bld, modname, 'EMPTY')
+            return
+        empty_c = modname + '.empty.c'
+        bld.SAMBA_GENERATOR('%s_empty_c' % modname,
+                            rule=generate_empty_file,
+                            target=empty_c)
+        source=empty_c
 
     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
         return
 
     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
         return
@@ -538,7 +606,7 @@ def SAMBA_SUBSYSTEM(bld, modname, source,
 
     bld.SET_BUILD_GROUP(group)
 
 
     bld.SET_BUILD_GROUP(group)
 
-    features = 'cc'
+    features = 'c'
     if pyext:
         features += ' pyext'
     if pyembed:
     if pyext:
         features += ' pyext'
     if pyembed:
@@ -548,7 +616,9 @@ def SAMBA_SUBSYSTEM(bld, modname, source,
         features       = features,
         source         = source,
         target         = modname,
         features       = features,
         source         = source,
         target         = modname,
-        samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags, hide_symbols=hide_symbols),
+        samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags,
+                                        allow_warnings=allow_warnings,
+                                        hide_symbols=hide_symbols),
         depends_on     = depends_on,
         samba_deps     = TO_LIST(deps),
         samba_includes = includes,
         depends_on     = depends_on,
         samba_deps     = TO_LIST(deps),
         samba_includes = includes,
@@ -578,8 +648,10 @@ def SAMBA_GENERATOR(bld, name, rule, source='', target='',
                     group='generators', enabled=True,
                     public_headers=None,
                     public_headers_install=True,
                     group='generators', enabled=True,
                     public_headers=None,
                     public_headers_install=True,
+                    private_headers=None,
                     header_path=None,
                     vars=None,
                     header_path=None,
                     vars=None,
+                    dep_vars=[],
                     always=False):
     '''A generic source generator target'''
 
                     always=False):
     '''A generic source generator target'''
 
@@ -589,11 +661,8 @@ def SAMBA_GENERATOR(bld, name, rule, source='', target='',
     if not enabled:
         return
 
     if not enabled:
         return
 
-    dep_vars = []
-    if isinstance(vars, dict):
-        dep_vars = vars.keys()
-    elif isinstance(vars, list):
-        dep_vars = vars
+    dep_vars.append('ruledeps')
+    dep_vars.append('SAMBA_GENERATOR_VARS')
 
     bld.SET_BUILD_GROUP(group)
     t = bld(
 
     bld.SET_BUILD_GROUP(group)
     t = bld(
@@ -601,13 +670,17 @@ def SAMBA_GENERATOR(bld, name, rule, source='', target='',
         source=bld.EXPAND_VARIABLES(source, vars=vars),
         target=target,
         shell=isinstance(rule, str),
         source=bld.EXPAND_VARIABLES(source, vars=vars),
         target=target,
         shell=isinstance(rule, str),
-        on_results=True,
-        before='cc',
+        update_outputs=True,
+        before='c',
         ext_out='.c',
         samba_type='GENERATOR',
         ext_out='.c',
         samba_type='GENERATOR',
-        dep_vars = [rule] + dep_vars,
+        dep_vars = dep_vars,
         name=name)
 
         name=name)
 
+    if vars is None:
+        vars = {}
+    t.env.SAMBA_GENERATOR_VARS = vars
+
     if always:
         t.always = True
 
     if always:
         t.always = True
 
@@ -619,7 +692,7 @@ Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
 
 
 
 
 
 
-@runonce
+@Utils.run_once
 def SETUP_BUILD_GROUPS(bld):
     '''setup build groups used to ensure that the different build
     phases happen consecutively'''
 def SETUP_BUILD_GROUPS(bld):
     '''setup build groups used to ensure that the different build
     phases happen consecutively'''
@@ -672,7 +745,7 @@ def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
     '''used to copy scripts from the source tree into the build directory
        for use by selftest'''
 
     '''used to copy scripts from the source tree into the build directory
        for use by selftest'''
 
-    source = bld.path.ant_glob(pattern)
+    source = bld.path.ant_glob(pattern, flat=True)
 
     bld.SET_BUILD_GROUP('build_source')
     for s in TO_LIST(source):
 
     bld.SET_BUILD_GROUP('build_source')
     for s in TO_LIST(source):
@@ -682,7 +755,7 @@ def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
         target = os.path.join(installdir, iname)
         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
         mkdir_p(tgtdir)
         target = os.path.join(installdir, iname)
         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
         mkdir_p(tgtdir)
-        link_src = os.path.normpath(os.path.join(bld.curdir, s))
+        link_src = os.path.normpath(os.path.join(bld.path.abspath(), s))
         link_dst = os.path.join(tgtdir, os.path.basename(iname))
         if os.path.islink(link_dst) and os.readlink(link_dst) == link_src:
             continue
         link_dst = os.path.join(tgtdir, os.path.basename(iname))
         if os.path.islink(link_dst) and os.readlink(link_dst) == link_src:
             continue
@@ -703,8 +776,6 @@ def copy_and_fix_python_path(task):
         replacement="""sys.path.insert(0, "%s")
 sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"])
 
         replacement="""sys.path.insert(0, "%s")
 sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"])
 
-    shebang = None
-
     if task.env["PYTHON"][0] == "/":
         replacement_shebang = "#!%s\n" % task.env["PYTHON"]
     else:
     if task.env["PYTHON"][0] == "/":
         replacement_shebang = "#!%s\n" % task.env["PYTHON"]
     else:
@@ -716,20 +787,52 @@ sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"])
     lineno = 0
     for line in source_file:
         newline = line
     lineno = 0
     for line in source_file:
         newline = line
-        if lineno == 0 and task.env["PYTHON_SPECIFIED"] == True and line[:2] == "#!":
+        if (lineno == 0 and task.env["PYTHON_SPECIFIED"] is True and
+                line[:2] == "#!"):
             newline = replacement_shebang
         elif pattern in line:
             newline = line.replace(pattern, replacement)
         installed_file.write(newline)
         lineno = lineno + 1
     installed_file.close()
             newline = replacement_shebang
         elif pattern in line:
             newline = line.replace(pattern, replacement)
         installed_file.write(newline)
         lineno = lineno + 1
     installed_file.close()
-    os.chmod(installed_location, 0755)
+    os.chmod(installed_location, 0o755)
+    return 0
+
+def copy_and_fix_perl_path(task):
+    pattern='use lib "$RealBin/lib";'
+
+    replacement = ""
+    if not task.env["PERL_LIB_INSTALL_DIR"] in task.env["PERL_INC"]:
+         replacement = 'use lib "%s";' % task.env["PERL_LIB_INSTALL_DIR"]
+
+    if task.env["PERL"][0] == "/":
+        replacement_shebang = "#!%s\n" % task.env["PERL"]
+    else:
+        replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PERL"]
+
+    installed_location=task.outputs[0].bldpath(task.env)
+    source_file = open(task.inputs[0].srcpath(task.env))
+    installed_file = open(installed_location, 'w')
+    lineno = 0
+    for line in source_file:
+        newline = line
+        if lineno == 0 and task.env["PERL_SPECIFIED"] == True and line[:2] == "#!":
+            newline = replacement_shebang
+        elif pattern in line:
+            newline = line.replace(pattern, replacement)
+        installed_file.write(newline)
+        lineno = lineno + 1
+    installed_file.close()
+    os.chmod(installed_location, 0o755)
     return 0
 
 
 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
     return 0
 
 
 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
-                 python_fixup=False, destname=None, base_name=None):
+                 python_fixup=False, perl_fixup=False,
+                 destname=None, base_name=None):
     '''install a file'''
     '''install a file'''
+    if not isinstance(file, str):
+        file = file.abspath()
     destdir = bld.EXPAND_VARIABLES(destdir)
     if not destname:
         destname = file
     destdir = bld.EXPAND_VARIABLES(destdir)
     if not destname:
         destname = file
@@ -737,16 +840,22 @@ def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
             destname = os.path.basename(destname)
     dest = os.path.join(destdir, destname)
     if python_fixup:
             destname = os.path.basename(destname)
     dest = os.path.join(destdir, destname)
     if python_fixup:
-        # fixup the python path it will use to find Samba modules
+        # fix the path python will use to find Samba modules
         inst_file = file + '.inst'
         bld.SAMBA_GENERATOR('python_%s' % destname,
                             rule=copy_and_fix_python_path,
         inst_file = file + '.inst'
         bld.SAMBA_GENERATOR('python_%s' % destname,
                             rule=copy_and_fix_python_path,
+                            dep_vars=["PYTHON","PYTHON_SPECIFIED","PYTHONDIR","PYTHONARCHDIR"],
+                            source=file,
+                            target=inst_file)
+        file = inst_file
+    if perl_fixup:
+        # fix the path perl will use to find Samba modules
+        inst_file = file + '.inst'
+        bld.SAMBA_GENERATOR('perl_%s' % destname,
+                            rule=copy_and_fix_perl_path,
+                            dep_vars=["PERL","PERL_SPECIFIED","PERL_LIB_INSTALL_DIR"],
                             source=file,
                             target=inst_file)
                             source=file,
                             target=inst_file)
-        bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONARCHDIR"])
-        bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONDIR"])
-        bld.add_manual_dependency(bld.path.find_or_declare(inst_file), str(bld.env["PYTHON_SPECIFIED"]))
-        bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHON"])
         file = inst_file
     if base_name:
         file = os.path.join(base_name, file)
         file = inst_file
     if base_name:
         file = os.path.join(base_name, file)
@@ -754,19 +863,20 @@ def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
 
 
 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
 
 
 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
-                  python_fixup=False, destname=None, base_name=None):
+                  python_fixup=False, perl_fixup=False,
+                  destname=None, base_name=None):
     '''install a set of files'''
     for f in TO_LIST(files):
         install_file(bld, destdir, f, chmod=chmod, flat=flat,
     '''install a set of files'''
     for f in TO_LIST(files):
         install_file(bld, destdir, f, chmod=chmod, flat=flat,
-                     python_fixup=python_fixup, destname=destname,
-                     base_name=base_name)
+                     python_fixup=python_fixup, perl_fixup=perl_fixup,
+                     destname=destname, base_name=base_name)
 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
 
 
 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
                      python_fixup=False, exclude=None, trim_path=None):
     '''install a set of files matching a wildcard pattern'''
 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
 
 
 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
                      python_fixup=False, exclude=None, trim_path=None):
     '''install a set of files matching a wildcard pattern'''
-    files=TO_LIST(bld.path.ant_glob(pattern))
+    files=TO_LIST(bld.path.ant_glob(pattern, flat=True))
     if trim_path:
         files2 = []
         for f in files:
     if trim_path:
         files2 = []
         for f in files:
@@ -781,13 +891,33 @@ def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
                   python_fixup=python_fixup, base_name=trim_path)
 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
 
                   python_fixup=python_fixup, base_name=trim_path)
 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
 
+def INSTALL_DIR(bld, path, chmod=0o755, env=None):
+    """Install a directory if it doesn't exist, always set permissions."""
 
 
-def INSTALL_DIRS(bld, destdir, dirs):
+    if not path:
+        return []
+
+    destpath = bld.EXPAND_VARIABLES(path)
+    if Options.options.destdir:
+        destpath = os.path.join(Options.options.destdir, destpath.lstrip(os.sep))
+
+    if bld.is_install > 0:
+        if not os.path.isdir(destpath):
+            try:
+                Logs.info('* create %s', destpath)
+                os.makedirs(destpath)
+                os.chmod(destpath, chmod)
+            except OSError as e:
+                if not os.path.isdir(destpath):
+                    raise Errors.WafError("Cannot create the folder '%s' (error: %s)" % (path, e))
+Build.BuildContext.INSTALL_DIR = INSTALL_DIR
+
+def INSTALL_DIRS(bld, destdir, dirs, chmod=0o755, env=None):
     '''install a set of directories'''
     destdir = bld.EXPAND_VARIABLES(destdir)
     dirs = bld.EXPAND_VARIABLES(dirs)
     for d in TO_LIST(dirs):
     '''install a set of directories'''
     destdir = bld.EXPAND_VARIABLES(destdir)
     dirs = bld.EXPAND_VARIABLES(dirs)
     for d in TO_LIST(dirs):
-        bld.install_dir(os.path.join(destdir, d))
+        INSTALL_DIR(bld, os.path.join(destdir, d), chmod, env)
 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
 
 
 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
 
 
@@ -806,79 +936,30 @@ def MANPAGES(bld, manpages, install):
             bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
 Build.BuildContext.MANPAGES = MANPAGES
 
             bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
 Build.BuildContext.MANPAGES = MANPAGES
 
-def SAMBAMANPAGES(bld, manpages):
+def SAMBAMANPAGES(bld, manpages, extra_source=None):
     '''build and install manual pages'''
     bld.env.SAMBA_EXPAND_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/expand-sambadoc.xsl'
     bld.env.SAMBA_MAN_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/man.xsl'
     '''build and install manual pages'''
     bld.env.SAMBA_EXPAND_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/expand-sambadoc.xsl'
     bld.env.SAMBA_MAN_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/man.xsl'
-    bld.env.SAMBA_CATALOGS = 'file:///etc/xml/catalog file:///usr/local/share/xml/catalog file://' + bld.srcnode.abspath() + '/bin/default/docs-xml/build/catalog.xml'
+    bld.env.SAMBA_CATALOG = bld.srcnode.abspath() + '/bin/default/docs-xml/build/catalog.xml'
+    bld.env.SAMBA_CATALOGS = 'file:///etc/xml/catalog file:///usr/local/share/xml/catalog file://' + bld.env.SAMBA_CATALOG
 
     for m in manpages.split():
         source = m + '.xml'
 
     for m in manpages.split():
         source = m + '.xml'
+        if extra_source is not None:
+            source = [source, extra_source]
         bld.SAMBA_GENERATOR(m,
                             source=source,
                             target=m,
                             group='final',
         bld.SAMBA_GENERATOR(m,
                             source=source,
                             target=m,
                             group='final',
+                            dep_vars=['SAMBA_MAN_XSL', 'SAMBA_EXPAND_XSL', 'SAMBA_CATALOG'],
                             rule='''XML_CATALOG_FILES="${SAMBA_CATALOGS}"
                                     export XML_CATALOG_FILES
                             rule='''XML_CATALOG_FILES="${SAMBA_CATALOGS}"
                                     export XML_CATALOG_FILES
-                                    ${XSLTPROC} --xinclude --stringparam noreference 0 -o ${TGT}.xml --nonet ${SAMBA_EXPAND_XSL} ${SRC}
+                                    ${XSLTPROC} --xinclude --stringparam noreference 0 -o ${TGT}.xml --nonet ${SAMBA_EXPAND_XSL} ${SRC[0].abspath(env)}
                                     ${XSLTPROC} --nonet -o ${TGT} ${SAMBA_MAN_XSL} ${TGT}.xml'''
                             )
         bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
 Build.BuildContext.SAMBAMANPAGES = SAMBAMANPAGES
 
                                     ${XSLTPROC} --nonet -o ${TGT} ${SAMBA_MAN_XSL} ${TGT}.xml'''
                             )
         bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
 Build.BuildContext.SAMBAMANPAGES = SAMBAMANPAGES
 
-#############################################################
-# give a nicer display when building different types of files
-def progress_display(self, msg, fname):
-    col1 = Logs.colors(self.color)
-    col2 = Logs.colors.NORMAL
-    total = self.position[1]
-    n = len(str(total))
-    fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
-    return fs % (self.position[0], self.position[1], col1, fname, col2)
-
-def link_display(self):
-    if Options.options.progress_bar != 0:
-        return Task.Task.old_display(self)
-    fname = self.outputs[0].bldpath(self.env)
-    return progress_display(self, 'Linking', fname)
-Task.TaskBase.classes['cc_link'].display = link_display
-
-def samba_display(self):
-    if Options.options.progress_bar != 0:
-        return Task.Task.old_display(self)
-
-    targets    = LOCAL_CACHE(self, 'TARGET_TYPE')
-    if self.name in targets:
-        target_type = targets[self.name]
-        type_map = { 'GENERATOR' : 'Generating',
-                     'PROTOTYPE' : 'Generating'
-                     }
-        if target_type in type_map:
-            return progress_display(self, type_map[target_type], self.name)
-
-    if len(self.inputs) == 0:
-        return Task.Task.old_display(self)
-
-    fname = self.inputs[0].bldpath(self.env)
-    if fname[0:3] == '../':
-        fname = fname[3:]
-    ext_loc = fname.rfind('.')
-    if ext_loc == -1:
-        return Task.Task.old_display(self)
-    ext = fname[ext_loc:]
-
-    ext_map = { '.idl' : 'Compiling IDL',
-                '.et'  : 'Compiling ERRTABLE',
-                '.asn1': 'Compiling ASN1',
-                '.c'   : 'Compiling' }
-    if ext in ext_map:
-        return progress_display(self, ext_map[ext], fname)
-    return Task.Task.old_display(self)
-
-Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
-Task.TaskBase.classes['Task'].display = samba_display
-
-
 @after('apply_link')
 @feature('cshlib')
 def apply_bundle_remove_dynamiclib_patch(self):
 @after('apply_link')
 @feature('cshlib')
 def apply_bundle_remove_dynamiclib_patch(self):