diff --git a/compiler/Makefile.am b/compiler/Makefile.am index d6e7f81..fc25be4 100644 --- a/compiler/Makefile.am +++ b/compiler/Makefile.am @@ -7,7 +7,9 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/vala \ -I$(top_srcdir)/codegen \ $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \ + -DPACKAGE_LIBEXECDIR=\"$(pkglibexecdir)\" \ $(NULL) BUILT_SOURCES = valac.vala.stamp @@ -26,12 +28,13 @@ valac_SOURCES = \ $(NULL) valac.vala.stamp: $(valac_VALASOURCES) - $(VALA_V)$(VALAC) $(COVERAGE_VALAFLAGS) $(VALAFLAGS) -C --vapidir $(srcdir)/../vapi --pkg gobject-2.0 --vapidir $(srcdir)/../gee --pkg gee --vapidir $(srcdir)/../ccode --pkg ccode --vapidir $(srcdir)/../vala --pkg vala --vapidir $(srcdir)/../codegen --pkg codegen --pkg config $^ + $(VALA_V)$(VALAC) $(COVERAGE_VALAFLAGS) $(VALAFLAGS) -C --vapidir $(srcdir)/../vapi --pkg gobject-2.0 --pkg gmodule-2.0 --vapidir $(srcdir)/../gee --pkg gee --vapidir $(srcdir)/../ccode --pkg ccode --vapidir $(srcdir)/../vala --pkg vala --vapidir $(srcdir)/../codegen --pkg codegen --pkg config $^ @touch $@ valac_LDADD = \ $(COVERAGE_LIBS) \ $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ ../codegen/libvala@PACKAGE_SUFFIX@.la \ $(NULL) diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index 174794e..af645d0 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -70,6 +70,8 @@ class Vala.Compiler { static string cc_command; [CCode (array_length = false, array_null_terminated = true)] static string[] cc_options; + [CCode (array_length = false, array_null_terminated = true)] + static string[] profile_plugin_options; static string dump_tree; static bool save_temps; [CCode (array_length = false, array_null_terminated = true)] @@ -77,6 +79,7 @@ class Vala.Compiler { static bool quiet_mode; static bool verbose_mode; static string profile; + static string profile_plugindir; static bool nostdpkg; static bool enable_version_header; static bool disable_version_header; @@ -89,6 +92,12 @@ class Vala.Compiler { private CodeContext context; + private Module? profile_module; + private CustomProfileFactoryDelegate custom_profile_factory; + + [CCode(has_target=false)] + private delegate Vala.CodeGenerator CustomProfileFactoryDelegate(Vala.CodeContext context, string[] profile_plugindir_options); + const OptionEntry[] options = { { "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..." }, @@ -132,6 +141,8 @@ class Vala.Compiler { { "dump-tree", 0, 0, OptionArg.FILENAME, ref dump_tree, "Write code tree to FILE", "FILE" }, { "save-temps", 0, 0, OptionArg.NONE, ref save_temps, "Keep temporary files", null }, { "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the default", "PROFILE" }, + { "profile-plugindir", 0, 0, OptionArg.STRING, ref profile_plugindir, "Directory used to search for profile plugins", "DIRECTORY" }, + { "profile-option", 0, 0, OptionArg.STRING_ARRAY, ref profile_plugin_options, "Pass OPTION to the profile plugin", "OPTION" }, { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null }, { "verbose", 'v', 0, OptionArg.NONE, ref verbose_mode, "Print additional messages to the console", null }, { "target-glib", 0, 0, OptionArg.STRING, ref target_glib, "Target version of glib for code generation", "MAJOR.MINOR" }, @@ -212,12 +223,34 @@ class Vala.Compiler { context.thread = thread; context.mem_profiler = mem_profiler; context.save_temps = save_temps; + + if (profile_plugindir == null) { + profile_plugindir = Config.PACKAGE_LIBEXECDIR; + } if (profile == "gobject-2.0" || profile == "gobject" || profile == null) { // default profile context.profile = Profile.GOBJECT; context.add_define ("GOBJECT"); } else { - Report.error (null, "Unknown profile %s".printf (profile)); + if (Module.supported()) { + string path = Module.build_path (profile_plugindir, "%s%s".printf(profile, Config.PACKAGE_SUFFIX)); + + profile_module = Module.open (path, ModuleFlags.BIND_LOCAL); + if (profile_module != null) { + void* codegen_factory_func; + + if (profile_module.symbol("vala_codegenerator_factory", out codegen_factory_func)) { + custom_profile_factory = (CustomProfileFactoryDelegate) codegen_factory_func; + context.profile = Profile.CUSTOM; + } else { + Report.error (null, "A valid factory function was not found. Can't use module '%s' for profile %s".printf (path, profile)); + } + } else { + Report.error (null, "Can't load module '%s'. Unknown profile %s".printf (path, profile)); + } + } else { + Report.error (null, "Unknown profile %s".printf (profile)); + } } nostdpkg |= fast_vapi_filename != null; context.nostdpkg = nostdpkg; @@ -248,14 +281,16 @@ class Vala.Compiler { Report.error (null, "This version of valac only supports GLib 2"); } - for (int i = 16; i <= glib_minor; i += 2) { - context.add_define ("GLIB_2_%d".printf (i)); - } + if (context.profile != Profile.CUSTOM) { + for (int i = 16; i <= glib_minor; i += 2) { + context.add_define ("GLIB_2_%d".printf (i)); + } - if (!nostdpkg) { - /* default packages */ - context.add_external_package ("glib-2.0"); - context.add_external_package ("gobject-2.0"); + if (!nostdpkg) { + /* default packages */ + context.add_external_package ("glib-2.0"); + context.add_external_package ("gobject-2.0"); + } } if (packages != null) { @@ -280,7 +315,16 @@ class Vala.Compiler { return quit (); } - context.codegen = new GDBusServerModule (); + if (context.profile == Profile.CUSTOM) { + var codegen = custom_profile_factory(context, profile_plugin_options) as Vala.CodeGenerator; + if (codegen != null) { + context.codegen = codegen; + } else { + Report.error (null, "Invalid code generator for profile %s".printf (profile)); + } + } else { + context.codegen = new GDBusServerModule (); + } bool has_c_files = false; diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala index b376723..7431078 100644 --- a/vala/valaarraytype.vala +++ b/vala/valaarraytype.vala @@ -165,12 +165,12 @@ public class Vala.ArrayType : ReferenceType { public override bool compatible (DataType target_type) { if (target_type.data_type != null) { - if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type) && element_type.data_type == CodeContext.get ().root.scope.lookup ("string")) { + if (CodeContext.get ().analyzer.gvalue_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type) && element_type.data_type == CodeContext.get ().root.scope.lookup ("string")) { // allow implicit conversion from string[] to GValue return true; } - if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) { + if (CodeContext.get ().analyzer.gvariant_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) { // allow implicit conversion to GVariant return true; } diff --git a/vala/valacastexpression.vala b/vala/valacastexpression.vala index c7a72b6..90371b8 100644 --- a/vala/valacastexpression.vala +++ b/vala/valacastexpression.vala @@ -163,7 +163,7 @@ public class Vala.CastExpression : Expression { } bool is_gvariant (CodeContext context, DataType type) { - return type.data_type != null && type.data_type.is_subtype_of (context.analyzer.gvariant_type.data_type); + return type.data_type != null && context.analyzer.gvariant_type != null && type.data_type.is_subtype_of (context.analyzer.gvariant_type.data_type); } public override void emit (CodeGenerator codegen) { diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index afad107..62fb4d4 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -412,9 +412,11 @@ public class Vala.CodeContext { source_file.relative_filename = filename; // import the GLib namespace by default (namespace of backend-specific standard library) - var ns_ref = new UsingDirective (new UnresolvedSymbol (null, "GLib", null)); - source_file.add_using_directive (ns_ref); - root.add_using_directive (ns_ref); + if (this.profile != Profile.CUSTOM) { + var ns_ref = new UsingDirective (new UnresolvedSymbol (null, "GLib", null)); + source_file.add_using_directive (ns_ref); + root.add_using_directive (ns_ref); + } add_source_file (source_file); } else if (filename.has_suffix (".vapi") || filename.has_suffix (".gir")) { diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 085d321..02ac63c 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -263,12 +263,12 @@ public abstract class Vala.DataType : CodeNode { } if (target_type.data_type != null) { - if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type)) { + if (CodeContext.get ().analyzer.gvalue_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type)) { // allow implicit conversion to GValue return true; } - if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) { + if (CodeContext.get ().analyzer.gvariant_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) { // allow implicit conversion to GVariant return true; } diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala index 8c65222..0b5f1ec 100644 --- a/vala/valaforeachstatement.vala +++ b/vala/valaforeachstatement.vala @@ -174,7 +174,7 @@ public class Vala.ForeachStatement : Block { array_type.inline_allocated = false; return check_without_iterator (context, collection_type, array_type.element_type); - } else if (collection_type.compatible (context.analyzer.glist_type) || collection_type.compatible (context.analyzer.gslist_type)) { + } else if ((context.analyzer.glist_type != null && collection_type.compatible (context.analyzer.glist_type)) || (context.analyzer.gslist_type != null && collection_type.compatible (context.analyzer.gslist_type))) { if (collection_type.get_type_arguments ().size != 1) { error = true; Report.error (collection.source_reference, "missing type argument for collection"); @@ -182,7 +182,7 @@ public class Vala.ForeachStatement : Block { } return check_without_iterator (context, collection_type, collection_type.get_type_arguments ().get (0)); - } else if (collection_type.compatible (context.analyzer.gvaluearray_type)) { + } else if (context.analyzer.gvaluearray_type != null && collection_type.compatible (context.analyzer.gvaluearray_type)) { return check_without_iterator (context, collection_type, context.analyzer.gvalue_type); } else { return check_with_iterator (context, collection_type); diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 89d2ba5..eac7136 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -220,7 +220,8 @@ public class Vala.MethodCall : Expression { CreationMethod base_cm = null; - if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) { + //if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) { + if (mtype is ObjectType || (context.analyzer.object_type != null && call.symbol_reference == context.analyzer.object_type)) { // constructor chain-up var cm = context.analyzer.find_current_method () as CreationMethod; if (cm == null) { diff --git a/vala/valapointertype.vala b/vala/valapointertype.vala index 4bfaf34..4f57641 100644 --- a/vala/valapointertype.vala +++ b/vala/valapointertype.vala @@ -83,7 +83,7 @@ public class Vala.PointerType : DataType { return base_type.compatible (target_type); } - if (target_type.data_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type)) { + if (target_type.data_type != null && CodeContext.get ().analyzer.gvalue_type != null && target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type)) { // allow implicit conversion to GValue return true; } diff --git a/vala/valaprofile.vala b/vala/valaprofile.vala index 8024965..a5aebdb 100644 --- a/vala/valaprofile.vala +++ b/vala/valaprofile.vala @@ -21,5 +21,6 @@ */ public enum Vala.Profile { - GOBJECT + GOBJECT, + CUSTOM } diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 8244896..c78c513 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -204,22 +204,24 @@ public class Vala.SemanticAnalyzer : CodeVisitor { unichar_type = new IntegerType (unichar_struct); } - var glib_ns = root_symbol.scope.lookup ("GLib"); + if (context.profile == Profile.GOBJECT) { + var glib_ns = root_symbol.scope.lookup ("GLib"); - object_type = (Class) glib_ns.scope.lookup ("Object"); - type_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Type")); - gvalue_type = new StructValueType ((Struct) glib_ns.scope.lookup ("Value")); - gvariant_type = new ObjectType ((Class) glib_ns.scope.lookup ("Variant")); + object_type = (Class) glib_ns.scope.lookup ("Object"); + type_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Type")); + gvalue_type = new StructValueType ((Struct) glib_ns.scope.lookup ("Value")); + gvariant_type = new ObjectType ((Class) glib_ns.scope.lookup ("Variant")); - glist_type = new ObjectType ((Class) glib_ns.scope.lookup ("List")); - gslist_type = new ObjectType ((Class) glib_ns.scope.lookup ("SList")); - garray_type = new ObjectType ((Class) glib_ns.scope.lookup ("Array")); - gvaluearray_type = new ObjectType ((Class) glib_ns.scope.lookup ("ValueArray")); + glist_type = new ObjectType ((Class) glib_ns.scope.lookup ("List")); + gslist_type = new ObjectType ((Class) glib_ns.scope.lookup ("SList")); + garray_type = new ObjectType ((Class) glib_ns.scope.lookup ("Array")); + gvaluearray_type = new ObjectType ((Class) glib_ns.scope.lookup ("ValueArray")); - gerror_type = (Class) glib_ns.scope.lookup ("Error"); - regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Regex")); + gsource_type = (Class) glib_ns.scope.lookup ("Source"); - gsource_type = (Class) glib_ns.scope.lookup ("Source"); + gerror_type = (Class) glib_ns.scope.lookup ("Error"); + regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Regex")); + } current_symbol = root_symbol; context.root.check (context); diff --git a/vapi/config.vapi b/vapi/config.vapi index 2c6df9e..aada11b 100644 --- a/vapi/config.vapi +++ b/vapi/config.vapi @@ -26,4 +26,5 @@ namespace Config { public const string BUILD_VERSION; public const string PACKAGE_DATADIR; public const string PACKAGE_SUFFIX; + public const string PACKAGE_LIBEXECDIR; }