[vala/wip/transform: 97/104] Load plugins with GModule



commit 6779a5e9a8416c7f114d3021eacc72de819fcff1
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Feb 4 22:25:08 2014 +0100

    Load plugins with GModule

 compiler/valacompiler.vala    |   11 ++++-
 configure.ac                  |    1 +
 vala/Makefile.am              |    5 ++-
 vala/valacodecontext.vala     |   83 ++++++++++++++++++++++++++++++++++++++++
 vala/valacodetransformer.vala |   85 +++++++++++++++++++++++++++++++++++-----
 vapi/config.vapi              |    1 +
 6 files changed, 171 insertions(+), 15 deletions(-)
---
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index 4621f05..a9e6a47 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -36,6 +36,8 @@ class Vala.Compiler {
        static string[] gir_directories;
        [CCode (array_length = false, array_null_terminated = true)]
        static string[] metadata_directories;
+       [CCode (array_length = false, array_null_terminated = true)]
+       static string[] plugin_directories;
        static string vapi_filename;
        static string library;
        static string gir;
@@ -93,6 +95,7 @@ class Vala.Compiler {
                { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings 
in DIRECTORY", "DIRECTORY..." },
                { "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for .gir files in 
DIRECTORY", "DIRECTORY..." },
                { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR 
.metadata files in DIRECTORY", "DIRECTORY..." },
+               { "plugindir", 0, 0, OptionArg.FILENAME_ARRAY, ref plugin_directories, "Look for Vala 
compiler plugins in DIRECTORY", "DIRECTORY..." },
                { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", 
"PACKAGE..." },
                { "vapi", 0, 0, OptionArg.FILENAME, ref vapi_filename, "Output VAPI file name", "FILE" },
                { "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
@@ -208,6 +211,7 @@ class Vala.Compiler {
                context.vapi_directories = vapi_directories;
                context.gir_directories = gir_directories;
                context.metadata_directories = metadata_directories;
+               context.plugin_directories = plugin_directories;
                context.debug = debug;
                context.thread = thread;
                context.mem_profiler = mem_profiler;
@@ -329,9 +333,10 @@ class Vala.Compiler {
                        }
                }
 
-               var transformer = new GDBusServerTransformer ();
-               transformer.head = transformer;
-               transformer.transform (context);
+               context.register_transformer (new GDBusServerTransformer ());
+               context.load_plugins ();
+               
+               context.transformer.transform (context);
 
                if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 
0)) {
                        return quit ();
diff --git a/configure.ac b/configure.ac
index 4fcda23..00cc9f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,6 +18,7 @@ AC_DEFINE_UNQUOTED(PACKAGE_SUFFIX, "$PACKAGE_SUFFIX", [Define to the suffix of t
 program_transform_name="s,\$\$,${PACKAGE_SUFFIX},"
 
 AC_SUBST(pkgdatadir, [${datadir}/vala${PACKAGE_SUFFIX}])
+AC_SUBST(pkglibdir, [${libdir}/vala${PACKAGE_SUFFIX}])
 
 # Checks for programs.
 AC_PROG_CC
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 0269609..a872483 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -4,7 +4,9 @@ AM_CPPFLAGS = \
        $(COVERAGE_CFLAGS) \
        -I$(top_srcdir)/gee \
        $(GLIB_CFLAGS) \
+       $(GMODULE_CFLAGS) \
        -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+       -DPACKAGE_LIBDIR=\"$(pkglibdir)\"       \
        $(NULL)
 
 BUILT_SOURCES = vala.vala.stamp
@@ -176,12 +178,13 @@ valainclude_HEADERS = \
        $(NULL)
 
 vala.vapi vala.vala.stamp: $(libvalacore_la_VALASOURCES)
-       $(VALA_V)$(VALAC) $(COVERAGE_VALAFLAGS) $(VALAFLAGS) -C --vapidir $(srcdir)/../vapi --pkg gobject-2.0 
--vapidir $(srcdir)/../gee --pkg gee --pkg config -H vala.h --library vala $^
+       $(VALA_V)$(VALAC) $(COVERAGE_VALAFLAGS) $(VALAFLAGS) -C --vapidir $(srcdir)/../vapi --pkg gobject-2.0 
--pkg gmodule-2.0 --vapidir $(srcdir)/../gee --pkg gee --pkg config -H vala.h --library vala $^
        @touch $@
 
 libvalacore_la_LIBADD = \
        $(COVERAGE_LIBS) \
        $(GLIB_LIBS) \
+       $(GMODULE_LIBS) \
        ../gee/libgee.la \
        $(NULL)
 
diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala
index afad107..e7fad9c 100644
--- a/vala/valacodecontext.vala
+++ b/vala/valacodecontext.vala
@@ -119,6 +119,11 @@ public class Vala.CodeContext {
        public string[] metadata_directories;
 
        /**
+        * List of directories where to find plugins.
+        */
+       public string[] plugin_directories;
+       
+       /**
         * Produce debug information.
         */
        public bool debug { get; set; }
@@ -216,6 +221,11 @@ public class Vala.CodeContext {
        public FlowAnalyzer flow_analyzer { get; private set; }
 
        /**
+        * The head of the transformers chain.
+        */
+       public CodeTransformer transformer { get; set; }
+
+       /**
         * The selected code generator.
         */
        public CodeGenerator codegen { get; set; }
@@ -471,6 +481,77 @@ public class Vala.CodeContext {
                flow_analyzer.analyze (this);
        }
 
+       public void load_plugins () {
+               if (!Module.supported ()) {
+                       return;
+               }
+
+               if (plugin_directories != null) {
+                       foreach (string dir in plugin_directories) {
+                               load_plugins_in_directory (dir);
+                       }
+               }
+
+               load_plugins_in_directory (Config.PACKAGE_LIBDIR);
+       }
+
+       public void load_plugins_in_directory (string dirname) {
+               Dir dir;
+               try {
+                       dir = Dir.open (dirname, 0);
+               } catch (Error e) {
+                       return;
+               }
+               
+               string? name = null;
+
+               while ((name = dir.read_name ()) != null) {
+                       string path = Path.build_filename (dirname, name);
+                       if (FileUtils.test (path, FileTest.IS_DIR)) {
+                               continue;
+                       }
+                       if (!name.has_prefix ("valaplugin")) {
+                               continue;
+                       }
+
+                       var mod = Module.open (path, ModuleFlags.BIND_LOCAL);
+
+                       if (mod == null) {
+                               if (verbose_mode) {
+                                       stdout.printf ("Could not load module: %s\n", path);
+                               }
+                               continue;
+                       } else {
+                               if (verbose_mode) {
+                                       stdout.printf ("Loaded module: %s\n", path);
+                               }
+                       }
+
+                       void* function;
+                       if (!mod.symbol ("vala_plugin_register", out function) || function == null) {
+                               if (verbose_mode) {
+                                       stdout.printf ("Could not load entry point for module %s\n", path);
+                               }
+                               continue;
+                       }
+
+                       unowned RegisterPluginFunction register_plugin = (RegisterPluginFunction) function;
+                       register_plugin (this);
+
+                       mod.make_resident ();
+               }
+       }
+
+       /**
+        * Set the given transformer as the head transformer
+        */
+       public void register_transformer (CodeTransformer transformer) {
+               transformer.next = this.transformer;
+               // Setting .head, will recursively set the head for the next transformers
+               transformer.head = transformer;
+               this.transformer = transformer;
+       }
+       
        public void add_define (string define) {
                defines.add (define);
        }
@@ -643,3 +724,5 @@ public class Vala.CodeContext {
                return rpath;
        }
 }
+
+public delegate void Vala.RegisterPluginFunction (Vala.CodeContext context);
\ No newline at end of file
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 785e6b8..c5e1ad5 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -24,17 +24,81 @@
  * Code visitor for transforming the code tree.
  */
 public class Vala.CodeTransformer : CodeVisitor {
-       public CodeContext context;
+       public CodeContext context {
+               get {
+                       return _head._context;
+               }
+               set {
+                       _head._context = value;
+               }
+       }
+       CodeContext _context;
 
-       public CodeBuilder b;
-       public ArrayList<CodeBuilder> builder_stack = new ArrayList<CodeBuilder> ();
-       public HashMap<string, CodeNode> wrapper_cache;
+       public CodeBuilder b {
+               get {
+                       return _head._b;
+               }
+               set {
+                       _head._b = value;
+               }
+       }
+       CodeBuilder _b;
+       
+       public ArrayList<CodeBuilder> builder_stack {
+               get {
+                       return _head._builder_stack;
+               }
+               set {
+                       _head._builder_stack = value;
+               }
+       }
+       ArrayList<CodeBuilder> _builder_stack;
+       
+       public HashMap<string, CodeNode> wrapper_cache {
+               get {
+                       return _head._wrapper_cache;
+               }
+               set {
+                       _head._wrapper_cache = value;
+               }
+       }
+       HashMap<string, CodeNode> _wrapper_cache;
+       
        /* Keep tracks of generated stuff to avoid cycles */
-       public HashSet<CodeNode> unit_generated = new HashSet<CodeNode> ();
+       public HashSet<CodeNode> unit_generated {
+               get {
+                       return _head._unit_generated;
+               }
+               set {
+                       _head._unit_generated = value;
+               }
+       }
+       HashSet<CodeNode> _unit_generated;
 
-       public Namespace current_namespace = null;
+       public Namespace current_namespace {
+               get {
+                       return _head._current_namespace;
+               }
+               set {
+                       _head._current_namespace = value;
+               }
+       }
+       Namespace _current_namespace;
 
-       public weak CodeTransformer head;
+       public weak CodeTransformer head {
+               get {
+                       return _head;
+               }
+               
+               set {
+                       _head = value;
+                       if (next != null) {
+                               next.head = value;
+                       }
+               }
+       }
+       private CodeTransformer _head;
+       
        public CodeTransformer next;
        
        public void push_builder (CodeBuilder builder) {
@@ -108,6 +172,9 @@ public class Vala.CodeTransformer : CodeVisitor {
         */
        public void transform (CodeContext context) {
                this.context = context;
+               builder_stack = new ArrayList<CodeBuilder> ();
+               unit_generated = new HashSet<CodeNode> ();
+               
                /* we're only interested in non-pkg source files */
                var source_files = context.get_source_files ();
                foreach (SourceFile file in source_files) {
@@ -329,10 +396,6 @@ public class Vala.CodeTransformer : CodeVisitor {
                next.visit_block (b);
        }
 
-       public override void visit_empty_statement (EmptyStatement stmt) {
-               next.visit_empty_statement (stmt);
-       }
-
        public override void visit_declaration_statement (DeclarationStatement stmt) {
                next.visit_declaration_statement (stmt);
        }
diff --git a/vapi/config.vapi b/vapi/config.vapi
index 2c6df9e..e4afb86 100644
--- a/vapi/config.vapi
+++ b/vapi/config.vapi
@@ -25,5 +25,6 @@ namespace Config {
        [CCode (cheader_filename = "version.h")]
        public const string BUILD_VERSION;
        public const string PACKAGE_DATADIR;
+       public const string PACKAGE_LIBDIR;
        public const string PACKAGE_SUFFIX;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]