wafsamba: introduce SAMBA[3]_PLUGIN()
authorStefan Metzmacher <metze@samba.org>
Fri, 20 Aug 2021 21:05:57 +0000 (23:05 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 30 Nov 2021 15:53:34 +0000 (15:53 +0000)
This will be used to define plugins we provide to be used
via dbopen/dlsym to external consumers.

SAMBA_PLUGIN() is used instead of SAMBA_LIBRARY() in order
to make it more strict that these plugins can't be used as
normal depedency by other subsystems and libraries.

With require_builtin_deps=True we make sure that only
symbols explicitly marked with _PUBLIC_ are exported
and we only link to system libraries and include all
internal depedencies as builtin subsystems.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14780

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
buildtools/wafsamba/samba3.py
buildtools/wafsamba/samba_deps.py
buildtools/wafsamba/samba_utils.py
buildtools/wafsamba/stale_files.py
buildtools/wafsamba/symbols.py
buildtools/wafsamba/wafsamba.py

index 7b42075d1abfb38c0e59a5256e2ef21b385ecabf..ebc7fbb707f000f51ded6217a9cea8e07ba65ad5 100644 (file)
@@ -85,6 +85,11 @@ def SAMBA3_LIBRARY(bld, name, *args, **kwargs):
     return bld.SAMBA_LIBRARY(name, *args, **kwargs)
 Build.BuildContext.SAMBA3_LIBRARY = SAMBA3_LIBRARY
 
+def SAMBA3_PLUGIN(bld, name, *args, **kwargs):
+    s3_fix_kwargs(bld, kwargs)
+    return bld.SAMBA_PLUGIN(name, *args, **kwargs)
+Build.BuildContext.SAMBA3_PLUGIN = SAMBA3_PLUGIN
+
 def SAMBA3_MODULE(bld, name, *args, **kwargs):
     s3_fix_kwargs(bld, kwargs)
     return bld.SAMBA_MODULE(name, *args, **kwargs)
index 5255d39e3bacb7687bf92c1d8fff1c2e1a947eeb..81979e291a7df2d1a1fc1d786569c1baa4e9c933 100644 (file)
@@ -77,7 +77,7 @@ def build_dependencies(self):
     the full dependency list for a target until we have all of the targets declared.
     '''
 
-    if self.samba_type in ['LIBRARY', 'BINARY', 'PYTHON']:
+    if self.samba_type in ['LIBRARY', 'PLUGIN', 'BINARY', 'PYTHON']:
         self.uselib        = list(self.final_syslibs)
         self.uselib_local  = list(self.final_libs)
         self.add_objects   = list(self.final_objects)
@@ -283,7 +283,7 @@ def check_duplicate_sources(bld, tgt_list):
 
     # build a list of targets that each source file is part of
     for t in tgt_list:
-        if not targets[t.sname] in [ 'LIBRARY', 'BINARY', 'PYTHON' ]:
+        if not targets[t.sname] in [ 'LIBRARY', 'PLUGIN', 'BINARY', 'PYTHON' ]:
             continue
         for obj in t.add_objects:
             t2 = t.bld.get_tgen_by_name(obj)
@@ -353,7 +353,7 @@ def show_final_deps(bld, tgt_list):
     targets = LOCAL_CACHE(bld, 'TARGET_TYPE')
 
     for t in tgt_list:
-        if not targets[t.sname] in ['LIBRARY', 'BINARY', 'PYTHON', 'SUBSYSTEM', 'BUILTIN']:
+        if not targets[t.sname] in ['LIBRARY', 'PLUGIN', 'BINARY', 'PYTHON', 'SUBSYSTEM', 'BUILTIN']:
             continue
         debug('deps: final dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s',
               t.sname, t.uselib, getattr(t, 'uselib_local', []), getattr(t, 'add_objects', []))
@@ -521,6 +521,10 @@ def build_direct_deps(bld, tgt_list):
                 t.direct_libs.add(d)
             elif t2.samba_type in [ 'SUBSYSTEM', 'BUILTIN', 'ASN1', 'PYTHON' ]:
                 t.direct_objects.add(d)
+            elif t2.samba_type in [ 'PLUGIN' ]:
+                Logs.error('Implicit dependency %s in %s is of type %s' % (
+                           d, t.sname, t2.samba_type))
+                sys.exit(1)
 
     debug('deps: built direct dependencies')
 
@@ -714,7 +718,7 @@ def break_dependency_loops(bld, tgt_list):
         if t.samba_type in ['SUBSYSTEM', 'BUILTIN']:
             loops[loop] = loops[loop].union(t.indirect_objects)
             loops[loop] = loops[loop].union(t.direct_objects)
-        if t.samba_type in ['LIBRARY','PYTHON']:
+        if t.samba_type in ['LIBRARY', 'PLUGIN', 'PYTHON']:
             loops[loop] = loops[loop].union(t.indirect_libs)
             loops[loop] = loops[loop].union(t.direct_libs)
         if loop in loops[loop]:
@@ -764,7 +768,7 @@ def reduce_objects(bld, tgt_list):
 
     changed = False
 
-    for type in ['BINARY', 'PYTHON', 'LIBRARY']:
+    for type in ['BINARY', 'PYTHON', 'LIBRARY', 'PLUGIN']:
         for t in tgt_list:
             if t.samba_type != type: continue
             # if we will indirectly link to a target then we don't need it
@@ -911,7 +915,7 @@ def calculate_final_deps(bld, tgt_list, loops):
     # we now need to make corrections for any library loops we broke up
     # any target that depended on the target of the loop and doesn't
     # depend on the source of the loop needs to get the loop source added
-    for type in ['BINARY','PYTHON','LIBRARY','BINARY']:
+    for type in ['BINARY','PYTHON','LIBRARY','PLUGIN','BINARY']:
         for t in tgt_list:
             if t.samba_type != type: continue
             for loop in loops:
@@ -944,7 +948,7 @@ def calculate_final_deps(bld, tgt_list, loops):
 
     # add in any syslib dependencies
     for t in tgt_list:
-        if not t.samba_type in ['BINARY','PYTHON','LIBRARY','SUBSYSTEM','BUILTIN']:
+        if not t.samba_type in ['BINARY','PYTHON','LIBRARY','PLUGIN','SUBSYSTEM','BUILTIN']:
             continue
         syslibs = set()
         for d in t.final_objects:
@@ -961,7 +965,7 @@ def calculate_final_deps(bld, tgt_list, loops):
     # find any unresolved library loops
     lib_loop_error = False
     for t in tgt_list:
-        if t.samba_type in ['LIBRARY', 'PYTHON']:
+        if t.samba_type in ['LIBRARY', 'PLUGIN', 'PYTHON']:
             for l in t.final_libs.copy():
                 t2 = bld.get_tgen_by_name(l)
                 if t.sname in t2.final_libs:
index cb13746a2c57fbc44627f3582cf4a958531e926b..863e9d5ba226a566a9b658b7782e68d1731f86e8 100644 (file)
@@ -658,7 +658,7 @@ def get_tgt_list(bld):
     tgt_list = []
     for tgt in targets:
         type = targets[tgt]
-        if not type in ['SUBSYSTEM', 'BUILTIN', 'MODULE', 'BINARY', 'LIBRARY', 'ASN1', 'PYTHON']:
+        if not type in ['SUBSYSTEM', 'BUILTIN', 'MODULE', 'BINARY', 'LIBRARY', 'PLUGIN', 'ASN1', 'PYTHON']:
             continue
         t = bld.get_tgen_by_name(tgt)
         if t is None:
index 175f573296eda0c58342e4fc4ca7bfee3dfef5a4..78efea424fd889ab7940770016a6854a0982f775 100644 (file)
@@ -69,7 +69,7 @@ def replace_refill_task_list(self):
                                 objpath = os.path.normpath(output.abspath(bld.env))
                                 expected.append(objpath)
                     for t in tlist:
-                        if ttype in ['LIBRARY','MODULE']:
+                        if ttype in ['LIBRARY', 'PLUGIN', 'MODULE']:
                             t = samba_utils.apply_pattern(t, bld.env.shlib_PATTERN)
                         if ttype == 'PYTHON':
                             t = samba_utils.apply_pattern(t, bld.env.pyext_PATTERN)
index f1e70c80d187301f0d9d4cb0577f14c46707c2cd..a6af1ac1485f2a43ace124673b1b5dd6173ca7fb 100644 (file)
@@ -252,7 +252,7 @@ def build_symbol_sets(bld, tgt_list):
             bld.env.public_symbols[name] = bld.env.public_symbols[name].union(t.public_symbols)
         else:
             bld.env.public_symbols[name] = t.public_symbols
-        if t.samba_type == 'LIBRARY':
+        if t.samba_type in ['LIBRARY', 'PLUGIN']:
             for dep in t.add_objects:
                 t2 = bld.get_tgen_by_name(dep)
                 bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep))
@@ -265,7 +265,7 @@ def build_symbol_sets(bld, tgt_list):
             bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t.used_symbols)
         else:
             bld.env.used_symbols[name] = t.used_symbols
-        if t.samba_type == 'LIBRARY':
+        if t.samba_type in ['LIBRARY', 'PLUGIN']:
             for dep in t.add_objects:
                 t2 = bld.get_tgen_by_name(dep)
                 bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep))
@@ -281,7 +281,7 @@ def build_library_dict(bld, tgt_list):
     bld.env.library_dict = {}
 
     for t in tgt_list:
-        if t.samba_type in [ 'LIBRARY', 'PYTHON' ]:
+        if t.samba_type in [ 'LIBRARY', 'PLUGIN', 'PYTHON' ]:
             linkpath = os.path.realpath(t.link_task.outputs[0].abspath(bld.env))
             bld.env.library_dict[linkpath] = t.sname
 
@@ -296,7 +296,7 @@ def build_syslib_sets(bld, tgt_list):
     syslibs = {}
     objmap = {}
     for t in tgt_list:
-        if getattr(t, 'uselib', []) and t.samba_type in [ 'LIBRARY', 'BINARY', 'PYTHON' ]:
+        if getattr(t, 'uselib', []) and t.samba_type in [ 'LIBRARY', 'PLUGIN', 'BINARY', 'PYTHON' ]:
             for lib in t.uselib:
                 if lib in ['PYEMBED', 'PYEXT']:
                     lib = "python"
@@ -386,7 +386,7 @@ def build_library_names(bld, tgt_list):
         t.in_library = []
 
     for t in tgt_list:
-        if t.samba_type in [ 'LIBRARY' ]:
+        if t.samba_type in ['LIBRARY', 'PLUGIN']:
             for obj in t.samba_deps_extended:
                 t2 = bld.get_tgen_by_name(obj)
                 if t2 and t2.samba_type in [ 'SUBSYSTEM', 'BUILTIN', 'ASN1' ]:
index 4a1a00c62c0523b9b4f9091d31f4c3436e31c92b..b0fd817410f49ee0431d350f2dc17fe18c451634 100644 (file)
@@ -55,11 +55,12 @@ def SAMBA_BUILD_ENV(conf):
     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, "plugins"))
     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
     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'default'))
-    for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('python', 'python')]:
+    for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('plugins', 'plugins'), ('python', 'python')]:
         link_target = os.path.join(conf.env.BUILD_DIRECTORY, 'default/' + target)
         if not os.path.lexists(link_target):
             symlink('../' + source, link_target)
@@ -141,15 +142,17 @@ def SAMBA_LIBRARY(bld, libname, source,
     # We support:
     # - LIBRARY: this can be use to link via -llibname
     # - MODULE:  this is module from SAMBA_MODULE()
+    # - PLUGIN:  this is plugin for external consumers to be
+    #            loaded via dlopen()
     # - PYTHON:  a python C binding library
     #
-    if target_type not in ['LIBRARY', 'MODULE', 'PYTHON']:
+    if target_type not in ['LIBRARY', 'MODULE', 'PLUGIN', 'PYTHON']:
         raise Errors.WafError("target_type[%s] not supported in SAMBA_LIBRARY('%s')" %
                               (target_type, libname))
 
     if require_builtin_deps:
-        # For now we only support require_builtin_deps only for libraries
-        if target_type not in ['LIBRARY']:
+        # For now we only support require_builtin_deps only for libraries, plugins
+        if target_type not in ['LIBRARY', 'PLUGIN']:
             raise Errors.WafError("target_type[%s] not supported SAMBA_LIBRARY('%s', require_builtin_deps=True)" %
                                   (target_type, libname))
 
@@ -157,7 +160,7 @@ def SAMBA_LIBRARY(bld, libname, source,
         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) and target_type not in ['PLUGIN']:
         private_library = True
 
     if not enabled:
@@ -623,6 +626,71 @@ def SAMBA_MODULE(bld, modname, source,
 
 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
 
+#################################################################
+def SAMBA_PLUGIN(bld, pluginname, source,
+                 deps='',
+                 includes='',
+                 vnum=None,
+                 soname=None,
+                 cflags='',
+                 ldflags='',
+                 local_include=True,
+                 global_include=True,
+                 vars=None,
+                 subdir=None,
+                 realname=None,
+                 keep_underscore=False,
+                 autoproto=None,
+                 autoproto_extra_source='',
+                 install_path=None,
+                 install=True,
+                 manpages=None,
+                 require_builtin_deps=True,
+                 allow_undefined_symbols=False,
+                 enabled=True):
+    '''define an external plugin.'''
+
+    bld.ASSERT(realname, "You must specify a realname for SAMBA_PLUGIN(%s)" % pluginname)
+
+    source = bld.EXPAND_VARIABLES(source, vars=vars)
+    if subdir:
+        source = bld.SUBDIR(subdir, source)
+
+    build_name = "_plugin_%s" % (pluginname)
+    build_link_name = "plugins/%s" % (realname)
+
+    bld.SAMBA_LIBRARY(pluginname,
+                      source,
+                      bundled_name=build_name,
+                      link_name=build_link_name,
+                      target_type='PLUGIN',
+                      deps=deps,
+                      includes=includes,
+                      vnum=vnum,
+                      soname=soname,
+                      cflags=cflags,
+                      ldflags=ldflags,
+                      realname=realname,
+                      autoproto=autoproto,
+                      autoproto_extra_source=autoproto_extra_source,
+                      local_include=local_include,
+                      global_include=global_include,
+                      vars=vars,
+                      group='main',
+                      install_path=install_path,
+                      install=install,
+                      manpages=manpages,
+                      require_builtin_deps=require_builtin_deps,
+                      builtin_cflags=cflags,
+                      hide_symbols=True,
+                      public_headers=[],
+                      public_headers_install=False,
+                      pc_files=[],
+                      allow_undefined_symbols=allow_undefined_symbols,
+                      allow_warnings=False,
+                      enabled=enabled)
+Build.BuildContext.SAMBA_PLUGIN = SAMBA_PLUGIN
+
 def __SAMBA_SUBSYSTEM_BUILTIN(bld, builtin_target, source,
                               deps='',
                               public_deps='',