From: Luca Bruno Date: Tue, 4 Feb 2014 21:25:08 +0000 (+0100) Subject: Load plugins with GModule X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff7ca09651e77147c9277de299b221d22ff485e2;p=thirdparty%2Fvala.git Load plugins with GModule --- diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index a508e6a9e..e17a5290e 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -38,6 +38,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 shared_library; @@ -105,6 +107,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" }, @@ -270,6 +273,7 @@ class Vala.Compiler { context.vapi_comments = vapi_comments; context.gir_directories = gir_directories; context.metadata_directories = metadata_directories; + context.plugin_directories = plugin_directories; context.debug = debug; context.mem_profiler = mem_profiler; context.save_temps = save_temps; @@ -403,9 +407,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/vala/Makefile.am b/vala/Makefile.am index 2c13f48d6..774c7bb12 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -8,6 +8,7 @@ AM_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) \ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \ + -DPACKAGE_LIBDIR=\"$(pkglibdir)\" \ $(NULL) BUILT_SOURCES = vala.vala.stamp $(srcdir)/valaversion.vala diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index 34543a8d9..b7fa6ed35 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -138,6 +138,11 @@ public class Vala.CodeContext { */ public string[] metadata_directories { get; set; default = {}; } + /** + * List of directories where to find plugins. + */ + public string[] plugin_directories; + /** * Produce debug information. */ @@ -228,6 +233,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. */ @@ -505,6 +515,77 @@ public class Vala.CodeContext { used_attr.check_unused (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) { if (is_defined (define)) { Report.warning (null, "`%s' is already defined".printf (define)); @@ -813,3 +894,5 @@ public class Vala.CodeContext { return output; } } + +public delegate void Vala.RegisterPluginFunction (Vala.CodeContext context); diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala index 4ba2d2538..c2c84a5d1 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 { + get { + return _head._b; + } + set { + _head._b = value; + } + } + CodeBuilder _b; + + public ArrayList builder_stack { + get { + return _head._builder_stack; + } + set { + _head._builder_stack = value; + } + } + ArrayList _builder_stack; + + public HashMap wrapper_cache { + get { + return _head._wrapper_cache; + } + set { + _head._wrapper_cache = value; + } + } + HashMap _wrapper_cache; - public CodeBuilder b; - public ArrayList builder_stack = new ArrayList (); - public HashMap wrapper_cache; /* Keep tracks of generated stuff to avoid cycles */ - public HashSet unit_generated = new HashSet (); + public HashSet unit_generated { + get { + return _head._unit_generated; + } + set { + _head._unit_generated = value; + } + } + HashSet _unit_generated; + + public Namespace current_namespace { + get { + return _head._current_namespace; + } + set { + _head._current_namespace = value; + } + } + Namespace _current_namespace; - public Namespace current_namespace = null; + public weak CodeTransformer head { + get { + return _head; + } + + set { + _head = value; + if (next != null) { + next.head = value; + } + } + } + private CodeTransformer _head; - public weak 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 (); + unit_generated = new HashSet (); + /* 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 c8b5d58a1..5ae26aab3 100644 --- a/vapi/config.vapi +++ b/vapi/config.vapi @@ -23,6 +23,7 @@ [CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] namespace Config { public const string PACKAGE_DATADIR; + public const string PACKAGE_LIBDIR; public const string PACKAGE_SUFFIX; public const string PACKAGE_VALADOC_LIBDIR; public const string PACKAGE_VALADOC_ICONDIR;