diff --git a/Makefile.am b/Makefile.am index 6af784f15a2acee97192b456f514fc4528077595..32b6f68a2755cccb9840af175993b2fdeeada817 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS = \ doc \ gobject-introspection \ vapigen \ + vapi2dbg \ $(NULL) if ENABLE_VALADOC diff --git a/ccode/valaccodefile.vala b/ccode/valaccodefile.vala index f61da07dfa1039868156bfdf87012613cadeace6..c49dc9fd70c4c7c00b2af720258820f844cfd4f4 100644 --- a/ccode/valaccodefile.vala +++ b/ccode/valaccodefile.vala @@ -26,6 +26,8 @@ public class Vala.CCodeFile { public weak SourceFile? file { get; private set; } + public string? fixed_text { get; set; } + Set features = new HashSet (str_hash, str_equal); Set declarations = new HashSet (str_hash, str_equal); Set definitions = new HashSet (str_hash, str_equal); @@ -166,6 +168,10 @@ public class Vala.CCodeFile { writer.write_newline (); include_directives.write (writer); writer.write_newline (); + if (fixed_text != null && fixed_text != "") { + writer.write_string (this.fixed_text); + writer.write_newline (); + } define_directives.write (writer); writer.write_newline (); type_declaration.write_combined (writer); diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 2f0ea22d8b9e0e33b85bf88db19f504661a8f9f7..5afac30567f5d1f5119ce1abffa1504473d4e08c 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -74,6 +74,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { List line_directive_stack = new ArrayList (); public Symbol current_symbol { get { return emit_context.current_symbol; } } + + public bool dry_run { get; set; default = false; } public TryStatement current_try { get { return emit_context.current_try; } @@ -276,6 +278,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { /* (constant) hash table with all reserved identifiers in the generated code */ public static Set reserved_identifiers; public static Set reserved_vala_identifiers; + public static List cfiles = new Vala.ArrayList (); public int next_temp_var_id { get { return emit_context.next_temp_var_id; } @@ -377,6 +380,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { public Map variable_name_map { get { return emit_context.variable_name_map; } } public static int ccode_attribute_cache_index = CodeNode.get_attribute_cache_index (); + + public bool emitted_signal_data; protected CCodeBaseModule () { if (Vala.get_build_version () != Vala.BUILD_VERSION) { @@ -585,15 +590,32 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { /* we're only interested in non-pkg source files */ var source_files = context.get_source_files (); + emitted_signal_data = false; foreach (SourceFile file in source_files) { if (file.file_type == SourceFileType.SOURCE || (context.header_filename != null && file.file_type == SourceFileType.FAST)) { file.accept (this); } } - + var idx = 0; + emitted_signal_data = false; + foreach (SourceFile file in source_files) { + if ((file.file_type == SourceFileType.SOURCE || + (context.header_filename != null && file.file_type == SourceFileType.FAST)) && idx < cfiles.size) { + var c = cfiles[idx++]; + if (!emitted_signal_data && context.debug) { + emitted_signal_data = true; + c.fixed_text = context.generate_signal_mappings_c (Vala.get_ccode_name, Vala.get_ccode_real_name); + } + if (!dry_run) { + if (!c.store (file.get_csource_filename (), file.filename, context.version_header, context.debug)) { + Report.error (null, "unable to open `%s' for writing", file.get_csource_filename ()); + } + } + } + } // generate symbols file for public API - if (context.symbols_filename != null) { + if (context.symbols_filename != null && !dry_run) { var stream = FileStream.open (context.symbols_filename, "w"); if (stream == null) { Report.error (null, "unable to open `%s' for writing", context.symbols_filename); @@ -610,7 +632,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } // generate C header file for public API - if (context.header_filename != null) { + if (context.header_filename != null && !dry_run) { bool ret; if (context.profile == Profile.GOBJECT) { header_file.add_include ("glib.h"); @@ -624,7 +646,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } // generate C header file for internal API - if (context.internal_header_filename != null) { + if (context.internal_header_filename != null && !dry_run) { bool ret; if (context.profile == Profile.GOBJECT) { internal_header_file.add_include ("glib.h"); @@ -927,10 +949,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } } - if (!cfile.store (source_file.get_csource_filename (), source_file.filename, context.version_header, context.debug)) { - Report.error (null, "unable to open `%s' for writing", source_file.get_csource_filename ()); - } - + cfiles.add (cfile); cfile = null; } diff --git a/codegen/valaccodecompiler.vala b/codegen/valaccodecompiler.vala index df2aa0d28965aad11ca7471c79a58459d1f864e4..12eaae7247ab34ce4da6edb9c69aef4798ec5cec 100644 --- a/codegen/valaccodecompiler.vala +++ b/codegen/valaccodecompiler.vala @@ -45,6 +45,7 @@ public class Vala.CCodeCompiler { pc += " " + pkg; } } + string? pkgflags; if (pc.length > 0) { pkgflags = context.pkg_config_compile_flags (pc); @@ -62,7 +63,7 @@ public class Vala.CCodeCompiler { } string cmdline = cc_command; if (context.debug) { - cmdline += " -g"; + cmdline += " -g3"; } if (context.compile_only) { cmdline += " -c"; diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala index 64ad460c3570548a6d9b0e0f5caae4e0806b37fb..051a64a0e16b859ced05f80b9874ea2d5db10553 100644 --- a/codegen/valaccodedelegatemodule.vala +++ b/codegen/valaccodedelegatemodule.vala @@ -197,6 +197,10 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule { // wrapper already defined return wrapper_name; } + + if (sig != null) { + context.signal_handlers_mapping[wrapper_name] = Vala.stringify_symbol (sig); + } // declaration var creturn_type = get_callable_creturn_type (d); diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala index 11389bade91068069408cfec300e6b90f082d577..0da17505c2b8182b6f0b89b85fa74bd54d2343ca 100644 --- a/codegen/valagsignalmodule.vala +++ b/codegen/valagsignalmodule.vala @@ -621,6 +621,8 @@ public class Vala.GSignalModule : GObjectModule { } else { connect_func = "g_signal_connect_after"; } + if (m != null) + context.signal_handlers_mapping[Vala.get_ccode_name (m)] = stringify_symbol (sig); } else { // disconnect if (sig is DynamicSignal) { diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index 13444d519f18e68b79dded74527791fb7e020040..5e03e637f28b0187109d9b013c6ec2fbebaa13c4 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -217,7 +217,7 @@ class Vala.Compiler { } } - private int run () { + private int run (uint hash_value) { context = new CodeContext (); CodeContext.push (context); @@ -245,6 +245,7 @@ class Vala.Compiler { } } + context.hash_value = hash_value; context.assert = !disable_assert; context.checking = enable_checking; context.deprecated = deprecated; @@ -577,8 +578,10 @@ class Vala.Compiler { library = null; shared_library = null; + var to_hash = string.joinv ("|", args); + var hash_value = str_hash (to_hash); var compiler = new Compiler (); - int ret = compiler.run (); + int ret = compiler.run (hash_value); if (ret != 0) { return ret; } @@ -656,7 +659,9 @@ class Vala.Compiler { return 1; } + var to_hash = string.joinv ("|", args); + var hash_value = str_hash (to_hash); var compiler = new Compiler (); - return compiler.run (); + return compiler.run (hash_value); } } diff --git a/configure.ac b/configure.ac index e2e31ea37a3921dea92aa708ef2c0205b158fb67..3755f56b8fae29ae2c5c959fbd86f604aaa100c8 100644 --- a/configure.ac +++ b/configure.ac @@ -293,6 +293,7 @@ AC_CONFIG_FILES([Makefile valadoc/icons/Makefile valadoc/tests/Makefile valadoc/tests/girwriter/Makefile + vapi2dbg/Makefile ]) AC_OUTPUT diff --git a/vala/Makefile.am b/vala/Makefile.am index 8f9f81cf288bfc1368764a71448aaf42cca714dc..d4d06270ee8544e178c6bd522aa9ee4bd17d1c35 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -33,6 +33,7 @@ libvala_la_VALASOURCES = \ valaarraymovemethod.vala \ valaarrayresizemethod.vala \ valaarraytype.vala \ + valaassemblyemitter.vala \ valaassignment.vala \ valaattribute.vala \ valabaseaccess.vala \ diff --git a/vala/valaassemblyemitter.vala b/vala/valaassemblyemitter.vala new file mode 100644 index 0000000000000000000000000000000000000000..df2f0afda884ac85825d52b896572b51bdd68257 --- /dev/null +++ b/vala/valaassemblyemitter.vala @@ -0,0 +1,50 @@ +/* valaassemblyemitter.vala + * + * Copyright 2022 JCWasmx86 + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see . + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ +// See https://stackoverflow.com/a/66249936 for the list +// of preprocessor defines + +public abstract class Vala.AssemblyEmitter { + public abstract string[] macros { get; protected set; } + + public abstract string emit_string (string s, bool zero_terminate = true); + public abstract string emit_u64 (uint64 u); + public abstract string emit_byte (int u); +} + +public class Vala.AMD64Emitter : Vala.AssemblyEmitter { + public override string[] macros { get; protected set; } + + public AMD64Emitter() { + this.macros = new string[]{"__x86_64__", "_M_X64"}; + } + + public override string emit_string (string s, bool zero_terminate = true) { + if (!zero_terminate) { + return "\".ascii \\\"%s\\\"\\n\"\n".printf (s); + } + return "\".string \\\"%s\\\"\\n\"\n".printf (s); + } + public override string emit_u64 (uint64 u) { + return "\".quad %llu\\n\"\n".printf (u); + } + public override string emit_byte (int u) requires (u >= 0 && u <= 255){ + return "\".byte %u\\n\"\n".printf (u); + } +} diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index 63dacd1a3007b760b68fafec6979139ade917c46..7694702ffcb0a9b7d7b4f886141746d9e701e80d 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -214,6 +214,10 @@ public class Vala.CodeContext { static StaticPrivate context_stack_key = StaticPrivate (); + public Map signal_handlers_mapping = new HashMap (str_hash, str_equal); + + public uint hash_value { get; set; } + int target_glib_major; int target_glib_minor; @@ -239,6 +243,238 @@ public class Vala.CodeContext { * Mark attributes used by the compiler and report unused at the end. */ public UsedAttr used_attr { get; set; } + + public delegate string CodeNodeToStringDelegate (CodeNode node); + public delegate string CodeNodeToRealStringDelegate (Symbol node); + + public unowned CodeNodeToStringDelegate d1; + public unowned CodeNodeToRealStringDelegate d2; + + public string generate_signal_mappings_c (CodeNodeToStringDelegate d1, CodeNodeToRealStringDelegate d2) { + if (!this.debug) + return ""; + this.d1 = d1; + this.d2 = d2; + var possible_architectures = new Vala.AssemblyEmitter[1]{new Vala.AMD64Emitter()}; + var sb = new StringBuilder (); + var into = new Vala.HashMap(str_hash, str_equal); + generate_metadata (into, this.root); + var deps = new Vala.HashSet (str_hash, str_equal); + find_deps (deps); + for (var i = 0; i < possible_architectures.length; i++) { + var a = possible_architectures[i]; + if (i == 0) { + sb.append ("#if "); + } else { + sb.append ("#elif "); + } + var defines = a.macros; + for (var j = 0; j < defines.length; j++) { + sb.append ("defined (").append (defines[j]).append (")"); + if (j != defines.length - 1) + sb.append (" || "); + else + sb.append ("\n"); + } + sb.append ("asm(\".section \\\".debug_info_vala\\\",\\\"\\\",@progbits\\n\"\n"); + sb.append (" %s".printf (a.emit_string ("VALA_DEBUG_INFO1", false))); + sb.append (" %s".printf (a.emit_u64 (0x1))); + sb.append (" %s".printf (a.emit_u64 (deps.size))); + foreach (var k in deps) { + sb.append (" %s".printf (a.emit_byte (k.length))); + sb.append (" %s".printf (a.emit_string (k))); + } + sb.append (" %s".printf (a.emit_u64 (into.size))); + foreach (var k in into.get_keys ()) { + sb.append (" %s".printf (a.emit_byte (k.length))); + sb.append (" %s".printf (a.emit_string (k))); + sb.append (" %s".printf (a.emit_byte (into[k].length))); + sb.append (" %s".printf (a.emit_string (into[k]))); + } + sb.append (" %s".printf (a.emit_u64 (signal_handlers_mapping.size))); + foreach (var k in signal_handlers_mapping.get_keys()) { + sb.append (" %s".printf (a.emit_byte (k.length))); + sb.append (" %s".printf (a.emit_string (k))); + sb.append (" %s".printf (a.emit_byte (signal_handlers_mapping[k].length))); + sb.append (" %s".printf (a.emit_string (signal_handlers_mapping[k]))); + } + sb.append(");\n"); + } + sb.append ("#else\n"); + sb.append ("#error Unsupported architecture for debuginfo\n"); + sb.append ("#endif"); + return sb.str; + } + + private void find_deps (Vala.Set into) { + foreach (var pkg in this.packages) + into.add (pkg); + while (true) { + var to_add = new Vala.HashSet (str_hash, str_equal); + foreach (var package_name in into) { + // TODO: Remove ccode and codegen + if (package_name == "posix" || package_name == "" || package_name == "ccode" || package_name == "codegen" || package_name == "gee" || package_name == "vala") + continue; + string pc = pkg_config_command + " --print-requires "; + pc += package_name; + + string? output = null; + int exit_status; + + try { + string? stderror; + Process.spawn_command_line_sync (pc, out output, out stderror, out exit_status); + if (exit_status != 0) { + // Report.error (null, "%s exited with status %d\n%s\n%s\n`%s'", pkg_config_command, exit_status, stderror, pc, package_name); + continue; + } + var lines = output.split("\n"); + foreach (var line in lines) { + if (!line.contains (" ")) { + to_add.add (line.strip ()); + continue; + } + var pkg = line.split(" ")[0]; + if (pkg != null && !into.contains (pkg) && !to_add.contains (pkg)) + to_add.add (pkg); + + } + } catch (SpawnError e) { + Report.error (null, e.message); + } + } + if (to_add.size == 0) + break; + var old = into.size; + foreach (var t in to_add) { + into.add (t); + } + if (into.size == old) + break; + to_add.clear (); + } + } + + private void insert_metadata (Vala.Map into, CodeNode n, string demangled_name, SourceFile? file) { + if (file != null && n.source_reference != null && n.source_reference.file.filename == file.filename) { + into.set (d1 (n), demangled_name); + return; + } + if (n.source_reference == null || (file == null && n.source_reference.file.file_type != SourceFileType.SOURCE)) + return; + + if (n.source_reference.file.filename.has_suffix (".vapi") && file == null) + return; + if (file != null && n.source_reference.file == file) + into.set (d1 (n), demangled_name); + else if (file == null) + into.set (d1 (n), demangled_name); + } + + public void generate_metadata (Vala.Map into, CodeNode n, string prefix = "", SourceFile? file = null) { + if (n is Namespace) { + var rn = ((Namespace)n); + var new_prefix = rn.name == null ? "" : (prefix + rn.name + "::"); + foreach (var e in rn.get_enums ()) { + generate_metadata (into, e, new_prefix, file); + } + foreach (var c in rn.get_classes ()) { + generate_metadata (into, c, new_prefix, file); + } + foreach (var e in rn.get_error_domains ()) { + generate_metadata (into, e, new_prefix, file); + } + foreach (var i in rn.get_interfaces ()) { + generate_metadata (into, i, new_prefix, file); + } + foreach (var m in rn.get_methods ()) { + generate_metadata (into, m, new_prefix, file); + } + foreach (var ns in rn.get_namespaces ()) { + generate_metadata (into, ns, new_prefix, file); + } + foreach (var s in rn.get_structs ()) { + generate_metadata (into, s, new_prefix, file); + } + } else if (n is ObjectTypeSymbol) { + var cc = ((ObjectTypeSymbol)n); + var new_prefix = prefix + cc.name + "."; + if (cc is Class) { + var ccc = (Class)cc; + if (ccc.class_constructor != null) { + insert_metadata (into, ccc.class_constructor, new_prefix + "", file); + } + if (ccc.class_destructor != null) { + insert_metadata (into, ccc.class_destructor, new_prefix + "", file); + } + if (ccc.constructor != null) { + insert_metadata (into, ccc.constructor, new_prefix + "", file); + } + if (ccc.destructor != null) { + insert_metadata (into, ccc.destructor, new_prefix + "", file); + } + // TODO: default_construction_method + if (ccc.static_constructor != null) { + insert_metadata (into, ccc.static_constructor, new_prefix + "", file); + } + if (ccc.static_destructor != null) { + insert_metadata (into, ccc.static_destructor, new_prefix + "", file); + } + } + foreach (var c in cc.get_classes ()) { + generate_metadata (into, c, new_prefix, file); + } + foreach (var e in cc.get_enums ()) { + generate_metadata (into, e, new_prefix, file); + } + foreach (var i in cc.get_interfaces ()) { + generate_metadata (into, i, new_prefix, file); + } + foreach (var m in cc.get_methods ()) { + generate_metadata (into, m, new_prefix, file); + } + foreach (var s in cc.get_signals ()) { + generate_metadata (into, s, new_prefix, file); + } + foreach (var s in cc.get_structs ()) { + generate_metadata (into, s, new_prefix, file); + } + // TODO: Properties + } else if (n is Enum) { + var e = ((Enum)n); + var new_prefix = prefix + e.name + "."; + foreach (var m in e.get_methods ()) { + generate_metadata (into, m, new_prefix, file); + } + } else if (n is ErrorDomain) { + var e = ((ErrorDomain)n); + var new_prefix = prefix + e.name + "."; + foreach (var m in e.get_methods ()) { + generate_metadata (into, m, new_prefix, file); + } + } else if (n is Method) { + var m = ((Method)n); + insert_metadata (into, n, prefix + m.name, file); + var is_real = d1 (n) != d2 (m); + var is_sourcefile = file == null && n.source_reference != null && n.source_reference.file != null && n.source_reference.file.filename.has_suffix (".vala"); + var is_vapi = n.source_reference != null && file != null && n.source_reference.file != null && n.source_reference.file.filename == file.filename; + if (is_real && (is_vapi || is_sourcefile)) + into[d2 (m)] = prefix + m.name; + } else if (n is Struct) { + var s = (Struct)n; + var new_prefix = prefix + s.name + "."; + foreach (var m in s.get_methods ()) { + generate_metadata (into, m, new_prefix, file); + } + } else if (n is Signal) { + // TODO: Do nothing? + // var s = (Signal)n; + // insert_metadata (into, n, prefix + s.name, file); + } else { + critical ("Unhandled codenode %s", n.type_name); + assert_not_reached (); + } + } public CodeContext () { add_default_defines (); diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala index 3ff39dbc8e7c9b9a862d302c58d49e4f7109d534..22e6d5c2e651c747d49615335d33c3c6ac60cae6 100644 --- a/vala/valacodenode.vala +++ b/vala/valacodenode.vala @@ -455,3 +455,17 @@ public abstract class Vala.CodeNode { public class Vala.AttributeCache { } + +namespace Vala { + public static string stringify_symbol (Symbol? s) { + if (s == null || s.name == null) + return ""; + if (s is Callable) + return stringify_symbol (s.parent_symbol) + s.name; + else if (s is Vala.ObjectTypeSymbol) + return stringify_symbol (s.parent_symbol) + s.name + "."; + else if (s is Vala.Namespace) + return stringify_symbol (s.parent_symbol) + s.name + "::"; + error ("FIXME: Type not handled in stringify_symbol: %s", s.type_name); + } +} diff --git a/vapi/Makefile.am b/vapi/Makefile.am index be1c1ff22a18e92aa9487b7cd85ec14150a02025..6e34a42fe6f7d324ee97c94bee04572bc385e691 100644 --- a/vapi/Makefile.am +++ b/vapi/Makefile.am @@ -9,6 +9,7 @@ check: $(top_builddir)/compiler/valac rm -f test.vala test.c vapidir = $(pkgdatadir)/vapi +vdbgdir = $(pkgdatadir)/vdbg dist_vapi_DATA = \ alsa.vapi \ @@ -451,16 +452,208 @@ GIR_BINDINGS = \ $(GSTREAMER_1_0_BINDINGS) \ $(NULL) +VAPIS = alsa.vapi \ + atk.vapi \ + atspi-2.vapi \ + avahi-client.vapi \ + avahi-gobject.vapi \ + bzlib.vapi \ + cairo-gobject.vapi \ + cairo.vapi \ + cairo-xcb.vapi \ + ccss-1.vapi \ + clutter-1.0.vapi \ + clutter-gdk-1.0.vapi \ + clutter-gst-2.0.vapi \ + clutter-gst-3.0.vapi \ + clutter-gtk-0.10.vapi \ + clutter-gtk-1.0.vapi \ + clutter-x11-1.0.vapi \ + cogl-1.0.vapi \ + cogl-pango-1.0.vapi \ + config.vapi \ + curses.vapi \ + dbus-glib-1.vapi \ + enchant-2.vapi \ + enchant.vapi \ + freetype2.vapi \ + fuse.vapi \ + gconf-2.0.vapi \ + gdesktopenums-3.0.vapi \ + gdk-2.0.vapi \ + gdk-3.0.vapi \ + gdk-pixbuf-2.0.vapi \ + gdk-x11-2.0.vapi \ + gdk-x11-3.0.vapi \ + gdl-1.0.vapi \ + gdl-3.0.vapi \ + geocode-glib-1.0.vapi \ + geocode-glib-2.0.vapi \ + gio-2.0.vapi \ + gio-unix-2.0.vapi \ + gio-windows-2.0.vapi \ + glib-2.0.vapi \ + gmodule-2.0.vapi \ + gnet-2.0.vapi \ + gnome-bg-4.vapi \ + gnome-desktop-2.0.vapi \ + gnome-desktop-3.0.vapi \ + gnome-desktop-4.vapi \ + gnome-rr-4.vapi \ + gnome-vfs-2.0.vapi \ + gnutls.vapi \ + gnu.vapi \ + gobject-2.0.vapi \ + gobject-introspection-1.0.vapi \ + goocanvas-2.0.vapi \ + goocanvas.vapi \ + graphene-1.0.vapi \ + graphene-gobject-1.0.vapi \ + gsl.vapi \ + gst-editing-services-1.0.vapi \ + gstreamer-1.0.vapi \ + gstreamer-allocators-1.0.vapi \ + gstreamer-app-1.0.vapi \ + gstreamer-audio-1.0.vapi \ + gstreamer-bad-allocators-1.0.vapi \ + gstreamer-base-1.0.vapi \ + gstreamer-check-1.0.vapi \ + gstreamer-controller-1.0.vapi \ + gstreamer-fft-1.0.vapi \ + gstreamer-net-1.0.vapi \ + gstreamer-pbutils-1.0.vapi \ + gstreamer-play-1.0.vapi \ + gstreamer-player-1.0.vapi \ + gstreamer-riff-1.0.vapi \ + gstreamer-rtp-1.0.vapi \ + gstreamer-rtsp-1.0.vapi \ + gstreamer-rtsp-server-1.0.vapi \ + gstreamer-sdp-1.0.vapi \ + gstreamer-tag-1.0.vapi \ + gstreamer-video-1.0.vapi \ + gstreamer-webrtc-1.0.vapi \ + gtk+-2.0.vapi \ + gtk+-3.0.vapi \ + gtk4-unix-print.vapi \ + gtk4.vapi \ + gtk4-wayland.vapi \ + gtk4-x11.vapi \ + gtkmozembed.vapi \ + gtksourceview-2.0.vapi \ + gtk+-unix-print-2.0.vapi \ + gtk+-unix-print-3.0.vapi \ + gudev-1.0.vapi \ + hal.vapi \ + harfbuzz-gobject.vapi \ + javascriptcoregtk-4.0.vapi \ + javascriptcoregtk-4.1.vapi \ + javascriptcoregtk-5.0.vapi \ + javascriptcoregtk-6.0.vapi \ + json-glib-1.0.vapi \ + libarchive.vapi \ + libbonoboui-2.0.vapi \ + libdaemon.vapi \ + libepc-1.0.vapi \ + libesmtp.vapi \ + libftdi.vapi \ + libgeoclue-2.0.vapi \ + libglade-2.0.vapi \ + libgnome-2.0.vapi \ + libgnome-menu-3.0.vapi \ + libgnome-menu.vapi \ + libgnomeui-2.0.vapi \ + libgrss.vapi \ + libgsf-1.vapi \ + libgvc.vapi \ + libmagic.vapi \ + libnl-1.vapi \ + libnl-2.0.vapi \ + libnl-3.0.vapi \ + libnotify.vapi \ + liboobs-1.vapi \ + libosso.vapi \ + libpanelapplet-2.0.vapi \ + libpeas-1.0.vapi \ + libpeas-gtk-1.0.vapi \ + libpq.vapi \ + libsexy.vapi \ + libsoup-2.4.vapi \ + libsoup-3.0.vapi \ + libunwind-generic.vapi \ + libusb-1.0.vapi \ + libusb.vapi \ + libwnck-1.0.vapi \ + libwnck-3.0.vapi \ + libxml-2.0.vapi \ + linux-media.vapi \ + linux.vapi \ + loudmouth-1.0.vapi \ + lua.vapi \ + mysql.vapi \ + orc-0.4.vapi \ + packagekit-glib2.vapi \ + pangocairo.vapi \ + pango.vapi \ + pixman-1.vapi \ + polkit-agent-1.vapi \ + polkit-gobject-1.vapi \ + poppler-glib.vapi \ + posix.vapi \ + purple.vapi \ + raptor.vapi \ + rasqal.vapi \ + readline.vapi \ + rest-0.7.vapi \ + rest-1.0.vapi \ + rest-extras-0.7.vapi \ + rest-extras-1.0.vapi \ + sdl2-android.vapi \ + SDL2_gfx.vapi \ + SDL2_image.vapi \ + sdl2-ios.vapi \ + SDL2_mixer.vapi \ + SDL2_net.vapi \ + SDL2_ttf.vapi \ + sdl2.vapi \ + sdl2-windows.vapi \ + sdl2-winrt.vapi \ + sqlite3.vapi \ + taglib_c.vapi \ + tiff.vapi \ + tokyocabinet.vapi \ + udisks2.vapi \ + unique-1.0.vapi \ + v4l2.vapi \ + wayland-client.vapi \ + webkit2gtk-4.0.vapi \ + webkit2gtk-4.1.vapi \ + webkit2gtk-5.0.vapi \ + webkit2gtk-web-extension-4.0.vapi \ + webkit2gtk-web-extension-4.1.vapi \ + webkit2gtk-web-extension-5.0.vapi \ + webkitgtk-6.0.vapi \ + webkitgtk-web-extension-6.0.vapi \ + x11.vapi \ + xcb-icccm.vapi \ + xcb.vapi \ + xtst.vapi \ + zlib.vapi + + BINDINGS = $(GIR_BINDINGS) $(GIDL_BINDINGS) VAPIGEN = $(top_builddir)/vapigen/vapigen$(EXEEXT) +VAPI2DBG = $(top_builddir)/vapi2dbg/vapi2dbg$(EXEEXT) + +dist_vdbg_DATA = $(VAPIS:.vapi=.vdbg) + VAPIGENFLAGS = --vapidir $(srcdir) GENVAPI = $(VAPIGEN) $(VAPIGENFLAGS) METADATADIR = $(srcdir)/metadata PACKAGESDIR = $(srcdir)/packages GIRDIR = $$($(PKG_CONFIG) gobject-introspection-1.0 --variable=girdir) -.PHONY: all-bindings $(BINDINGS) +.PHONY: all-bindings $(BINDINGS) $(VDBG_FILES) gir-bindings: $(GIR_BINDINGS) @@ -468,7 +661,12 @@ gidl-bindings: $(GIDL_BINDINGS) gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) -all-bindings: gir-bindings gidl-bindings +all-bindings: gir-bindings gidl-bindings $(dist_vdbg_DATA) + +all-vdbgs: $(dist_vdbg_DATA) + +%.vdbg: %.vapi + $(VAPI2DBG) $(VAPIGENFLAGS) $< -o $@ atk: $(GENVAPI) --library $(srcdir)/atk --metadatadir $(METADATADIR) $(METADATADIR)/Atk-1.0-custom.vala $(GIRDIR)/Atk-1.0.gir diff --git a/vapi2dbg/.gitignore b/vapi2dbg/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..58bcd053291574e981abc3ca0b3474739ddf45f3 --- /dev/null +++ b/vapi2dbg/.gitignore @@ -0,0 +1 @@ +vapi2dbg diff --git a/vapi2dbg/Makefile.am b/vapi2dbg/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..bbf7d811f774180f143a11d80813c9dd51a2258b --- /dev/null +++ b/vapi2dbg/Makefile.am @@ -0,0 +1,92 @@ +include $(top_srcdir)/Makefile.common + +NULL = + +SUBDIRS = \ + $(NULL) + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"vapi2dbg\" \ + $(COVERAGE_CFLAGS) \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/gee \ + -I$(top_srcdir)/ccode \ + -I$(top_srcdir)/codegen \ + -I$(top_srcdir)/vala \ + -I$(top_srcdir)/gobject-introspection \ + $(NULL) + +AM_LDFLAGS = \ + $(GLIB_LIBS) \ + -lgio-2.0 \ + -L$(top_srcdir)/codegen \ + -lvalaccodegen \ + $(NULL) + +bin_PROGRAMS = \ + vapi2dbg \ + $(NULL) + +noinst_PROGRAMS = \ + $(NULL) + +BUILT_SOURCES = vapi2dbg.vala.stamp + +vapi2dbg_VALASOURCES = \ + vapi2dbg.vala \ + $(NULL) + +vapi2dbg_SOURCES = \ + vapi2dbg.vala.stamp \ + $(vapi2dbg_VALASOURCES:.vala=.c) \ + $(NULL) + +vapi2dbg.vala.stamp: $(vapi2dbg_VALASOURCES) + $(VALA_V)$(VALAC) \ + $(COVERAGE_VALAFLAGS) \ + $(VALAFLAGS) \ + -C \ + --vapidir $(top_srcdir)/vapi \ + --vapidir $(top_srcdir)/gee --pkg gee \ + --vapidir $(top_srcdir)/vala --pkg vala \ + --vapidir $(top_srcdir)/gobject-introspection --pkg gidl \ + --vapidir $(top_srcdir)/ccode --pkg ccode \ + --vapidir $(top_srcdir)/codegen --pkg codegen \ + --pkg config \ + --pkg gio-2.0 \ + $^ + @touch $@ + +vapi2dbg_LDADD = \ + $(COVERAGE_LIBS) \ + $(GLIB_LIBS) \ + $(top_builddir)/vala/libvala@PACKAGE_SUFFIX@.la \ + $(top_builddir)/gobject-introspection/libgidl.la \ + $(NULL) + +if ENABLE_UNVERSIONED +makedir = $(datadir)/vala + +aclocaldir = $(datadir)/aclocal +endif + +pkgconfigdir = $(libdir)/pkgconfig + +EXTRA_DIST = \ + $(vapi2dbg_VALASOURCES) \ + vapi2dbg.vala.stamp \ + $(NULL) + +CLEANFILES = \ + vapi2dbg@PACKAGE_SUFFIX@.pc + $(NULL) + +install-exec-hook: + mkdir -p $(datarootdir)/vala/debug/ +if ENABLE_UNVERSIONED + cd $(DESTDIR)$(bindir) && $(LN_S) -f vapi2dbg@PACKAGE_SUFFIX@$(EXEEXT) vapi2dbg$(EXEEXT) +endif + +MAINTAINERCLEANFILES = \ + $(vapi2dbg_VALASOURCES:.vala=.c) \ + $(NULL) diff --git a/vapi2dbg/install_debug.sh b/vapi2dbg/install_debug.sh new file mode 100755 index 0000000000000000000000000000000000000000..4f500c85247d04f0439e2867a434937dd1dacdfe --- /dev/null +++ b/vapi2dbg/install_debug.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +for i in ../vapi/*.vapi; do + echo "Generating debuginfo for $(basename $i|sed s/.vapi$//g)" + ./vapi2dbg $i -o $1/$(basename $i|sed s/vapi/vdbg/g) || exit 1 +done diff --git a/vapi2dbg/vapi2dbg.vala b/vapi2dbg/vapi2dbg.vala new file mode 100644 index 0000000000000000000000000000000000000000..d752b20ded6488344794d1a12de68dd253bf9dd1 --- /dev/null +++ b/vapi2dbg/vapi2dbg.vala @@ -0,0 +1,164 @@ +using GLib; + +class Vala.Vapi2Dbg { + + static bool version; + static bool api_version; + [CCode (array_length = false, array_null_terminated = true)] + static string[] vapi_directories; + [CCode (array_length = false, array_null_terminated = true)] + 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[] packages; + static string vdbg_filename; + static string[] sources; + static bool quiet_mode; + + 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..." }, + { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR .metadata files in DIRECTORY", "DIRECTORY..." }, + { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." }, + { "output", 'o', 0, OptionArg.FILENAME, ref vdbg_filename, "Output vdbg file name", "FILE" }, + { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null }, + { "api-version", 0, 0, OptionArg.NONE, ref api_version, "Display API version number", null }, + { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null }, + { OPTION_REMAINING, 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." }, + { null } + }; + + private int run () { + var context = new CodeContext (); + CodeContext.push (context); + context.vapi_directories = vapi_directories; + context.gir_directories = gir_directories; + context.metadata_directories = metadata_directories; + var fp = sources[0].split(".vapi")[0]; + var splitted = fp.split("/"); + var name = splitted != null ? splitted[splitted.length - 1] : fp; + context.add_packages_from_file (sources[0].replace(".vapi", ".deps")); + if (packages != null) { + foreach (string package in packages) { + if (package == name) + continue; + context.add_external_package (package); + } + packages = null; + } + context.report.set_verbose_errors (!quiet_mode); + var s = new SourceFile (context, SourceFileType.PACKAGE, sources[0], null, true); + context.add_source_file (s); + context.pkg_config_command = Environment.get_variable ("PKG_CONFIG") ?? "pkg-config"; + if (name != "gobject-2.0" && name != "glib-2.0") + context.set_target_profile (Profile.GOBJECT, true); + var parser = new Parser (); + parser.parse (context); + var cg = new CCodeDelegateModule (); + context.codegen = cg; + cg.dry_run = true; + + if (context.report.get_errors () > 0) { + return quit (context); + } + context.check (); + + if (context.report.get_errors () > 0) { + return quit (context); + } + var into = new Vala.HashMap (str_hash, str_equal); + context.d1 = Vala.get_ccode_name; + context.d2 = Vala.get_ccode_real_name; + context.generate_metadata (into, context.root, "", s); + string output_name = null; + if (vdbg_filename != null) { + output_name = vdbg_filename; + } else { + output_name = name + ".vdbg"; + } + try { + var f = File.new_for_path (output_name); + if (f.query_exists ()) { + f.@delete (); + } + var ios = f.create_readwrite (FileCreateFlags.REPLACE_DESTINATION); + var dos = new DataOutputStream (ios.output_stream); + dos.set_byte_order (DataStreamByteOrder.BIG_ENDIAN); + dos.put_string ("VDBG"); + // Version + dos.put_byte (0x1); + // n Debug entries + dos.put_uint32 (into.size); + foreach (var k in into.get_keys ()) { + dos.put_uint16 ((uint16)k.length); + dos.put_string (k); + dos.put_byte (0x0); + var v = into[k]; + dos.put_uint16 ((uint16)v.length); + dos.put_string (v); + dos.put_byte (0x0); + } + } catch (GLib.Error e) { + Report.error (null, "Error writing vdbg file %s: %s", output_name, e.message); + } + return quit (context); + } + + private int quit (CodeContext context) { + if (context.report.get_errors () == 0 && context.report.get_warnings () == 0) { + CodeContext.pop (); + return 0; + } + if (context.report.get_errors () == 0) { + if (!quiet_mode) { + stdout.printf ("Compilation succeeded - %d warning(s)\n", context.report.get_warnings ()); + } + CodeContext.pop (); + return 0; + } else { + if (!quiet_mode) { + stdout.printf ("Compilation failed: %d error(s), %d warning(s)\n", context.report.get_errors (), context.report.get_warnings ()); + } + CodeContext.pop (); + return 1; + } + } + + static int main (string[] args) { + // initialize locale + Intl.setlocale (LocaleCategory.ALL, ""); + + if (Vala.get_build_version () != Vala.BUILD_VERSION) { + stderr.printf ("Integrity check failed (libvala %s doesn't match valac %s)\n", Vala.get_build_version (), Vala.BUILD_VERSION); + return 1; + } + + try { + var opt_context = new OptionContext ("- Vapi2Dbg"); + opt_context.set_help_enabled (true); + opt_context.add_main_entries (options, null); + opt_context.parse (ref args); + } catch (OptionError e) { + stdout.printf ("%s\n", e.message); + stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]); + return 1; + } + + if (version) { + stdout.printf ("Vapi2Dbg %s\n", Vala.BUILD_VERSION); + return 0; + } else if (api_version) { + stdout.printf ("%s\n", Vala.API_VERSION); + return 0; + } + + if (sources == null) { + stderr.printf ("No vapi file specified.\n"); + return 1; + } + + var runner = new Vapi2Dbg (); + return runner.run (); + } +}