From 23c8ae3e3f82b5141830aefaa204a449294128ac Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Sun, 24 Jul 2022 16:44:07 +0200 Subject: [PATCH 1/7] compiler: Add support for printing backtraces on signal. Depends on libvalabacktrace (https://github.com/JCWasmx86/libvalabacktrace) --- Makefile.am | 1 + ccode/valaccodefile.vala | 6 + codegen/valaccodebasemodule.vala | 35 +++- codegen/valaccodecompiler.vala | 3 +- codegen/valaccodedelegatemodule.vala | 4 + codegen/valagsignalmodule.vala | 2 + compiler/valacompiler.vala | 11 +- configure.ac | 1 + vala/Makefile.am | 1 + vala/valaassemblyemitter.vala | 50 ++++++ vala/valacodecontext.vala | 236 +++++++++++++++++++++++++++ vala/valacodenode.vala | 14 ++ vala/valalambdaexpression.vala | 1 + vapi2dbg/.gitignore | 1 + vapi2dbg/Makefile.am | 93 +++++++++++ vapi2dbg/install_debug.sh | 5 + vapi2dbg/vapi2dbg.vala | 164 +++++++++++++++++++ 17 files changed, 616 insertions(+), 12 deletions(-) create mode 100644 vala/valaassemblyemitter.vala create mode 100644 vapi2dbg/.gitignore create mode 100644 vapi2dbg/Makefile.am create mode 100755 vapi2dbg/install_debug.sh create mode 100644 vapi2dbg/vapi2dbg.vala diff --git a/Makefile.am b/Makefile.am index 6af784f15..32b6f68a2 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 f61da07df..c49dc9fd7 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 c2eefe02c..690f45fa6 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 df2aa0d28..12eaae724 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 64ad460c3..051a64a0e 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 4186859cf..c3cbab593 100644 --- a/codegen/valagsignalmodule.vala +++ b/codegen/valagsignalmodule.vala @@ -620,6 +620,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 13444d519..5e03e637f 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 0d0edaccf..3cc15357a 100644 --- a/configure.ac +++ b/configure.ac @@ -283,6 +283,7 @@ AC_CONFIG_FILES([Makefile valadoc/doclets/gtkdoc/Makefile valadoc/icons/Makefile valadoc/tests/Makefile + vapi2dbg/Makefile ]) AC_OUTPUT diff --git a/vala/Makefile.am b/vala/Makefile.am index 09f3c0672..c1fb0694f 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 000000000..df2f0afda --- /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 0ac4bbdf8..30f1f3547 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 4ca44c8d9..b78b6c709 100644 --- a/vala/valacodenode.vala +++ b/vala/valacodenode.vala @@ -445,3 +445,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/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala index be33765f8..0e68ba02f 100644 --- a/vala/valalambdaexpression.vala +++ b/vala/valalambdaexpression.vala @@ -151,6 +151,7 @@ public class Vala.LambdaExpression : Expression { var cb = (Delegate) ((DelegateType) target_type).delegate_symbol; var return_type = cb.return_type.get_actual_type (target_type, null, this); + // TODO: Integrate into debuginfo, so we can get nice backtraces method = new Method ("_lambda%d_".printf (next_lambda_id++), return_type, source_reference); // track usage for flow analyzer method.used = true; diff --git a/vapi2dbg/.gitignore b/vapi2dbg/.gitignore new file mode 100644 index 000000000..58bcd0532 --- /dev/null +++ b/vapi2dbg/.gitignore @@ -0,0 +1 @@ +vapi2dbg diff --git a/vapi2dbg/Makefile.am b/vapi2dbg/Makefile.am new file mode 100644 index 000000000..91535cad4 --- /dev/null +++ b/vapi2dbg/Makefile.am @@ -0,0 +1,93 @@ +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/ + ./install_debug.sh $(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 000000000..4f500c852 --- /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 000000000..edd31bbd8 --- /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); + 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); + context.vapi_directories = vapi_directories; + context.gir_directories = gir_directories; + context.metadata_directories = metadata_directories; + 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 (); + } +} -- GitLab From f6cc38ffc35aaf6da0581bee40ffe366c446d43b Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Tue, 27 Dec 2022 20:45:57 +0100 Subject: [PATCH 2/7] Add my progress for autotools. Doesn't work because I don't understand autotools --- vapi/Makefile.am | 199 ++++++++++++++++++++++++++++++++++++++++++- vapi2dbg/Makefile.am | 1 - 2 files changed, 197 insertions(+), 3 deletions(-) diff --git a/vapi/Makefile.am b/vapi/Makefile.am index 9097bc9b1..0f8a3ecd0 100644 --- a/vapi/Makefile.am +++ b/vapi/Makefile.am @@ -456,16 +456,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) + +VDBG_FILES = $(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) @@ -473,7 +665,10 @@ gidl-bindings: $(GIDL_BINDINGS) gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) -all-bindings: gir-bindings gidl-bindings +all-bindings: gir-bindings gidl-bindings $(vdbg_files) + +%.vdbg: %.vapi + $(VAPI2DBG) $< -o $@ atk: $(GENVAPI) --library $(srcdir)/atk --metadatadir $(METADATADIR) $(METADATADIR)/Atk-1.0-custom.vala $(GIRDIR)/Atk-1.0.gir diff --git a/vapi2dbg/Makefile.am b/vapi2dbg/Makefile.am index 91535cad4..bbf7d811f 100644 --- a/vapi2dbg/Makefile.am +++ b/vapi2dbg/Makefile.am @@ -83,7 +83,6 @@ CLEANFILES = \ install-exec-hook: mkdir -p $(datarootdir)/vala/debug/ - ./install_debug.sh $(datarootdir)/vala/debug/ if ENABLE_UNVERSIONED cd $(DESTDIR)$(bindir) && $(LN_S) -f vapi2dbg@PACKAGE_SUFFIX@$(EXEEXT) vapi2dbg$(EXEEXT) endif -- GitLab From ff0249a63765d1a49f5a4d2495eea085df210f2f Mon Sep 17 00:00:00 2001 From: Lorenz Wildberg Date: Mon, 24 Jul 2023 19:47:13 +0200 Subject: [PATCH 3/7] vapi2dbg: Add vapi directories earlier to avoid error --- vapi/Makefile.am | 2 +- vapi2dbg/vapi2dbg.vala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vapi/Makefile.am b/vapi/Makefile.am index 0f8a3ecd0..ac5fb0802 100644 --- a/vapi/Makefile.am +++ b/vapi/Makefile.am @@ -668,7 +668,7 @@ gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) all-bindings: gir-bindings gidl-bindings $(vdbg_files) %.vdbg: %.vapi - $(VAPI2DBG) $< -o $@ + $(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/vapi2dbg.vala b/vapi2dbg/vapi2dbg.vala index edd31bbd8..d752b20de 100644 --- a/vapi2dbg/vapi2dbg.vala +++ b/vapi2dbg/vapi2dbg.vala @@ -32,6 +32,9 @@ class Vala.Vapi2Dbg { 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; @@ -45,9 +48,6 @@ class Vala.Vapi2Dbg { packages = null; } context.report.set_verbose_errors (!quiet_mode); - context.vapi_directories = vapi_directories; - context.gir_directories = gir_directories; - context.metadata_directories = metadata_directories; 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"; -- GitLab From d00e124a894325087977a62410ba473a8c8486fb Mon Sep 17 00:00:00 2001 From: Lorenz Wildberg Date: Mon, 24 Jul 2023 20:58:45 +0200 Subject: [PATCH 4/7] Fix build system --- vapi/Makefile.am | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vapi/Makefile.am b/vapi/Makefile.am index ac5fb0802..4f9dd8341 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 \ @@ -649,7 +650,7 @@ BINDINGS = $(GIR_BINDINGS) $(GIDL_BINDINGS) VAPIGEN = $(top_builddir)/vapigen/vapigen$(EXEEXT) VAPI2DBG = $(top_builddir)/vapi2dbg/vapi2dbg$(EXEEXT) -VDBG_FILES = $(VAPIS:.vapi=.vdbg) +dist_vdbg_DATA = $(VAPIS:.vapi=.vdbg) VAPIGENFLAGS = --vapidir $(srcdir) GENVAPI = $(VAPIGEN) $(VAPIGENFLAGS) @@ -657,7 +658,7 @@ METADATADIR = $(srcdir)/metadata PACKAGESDIR = $(srcdir)/packages GIRDIR = $$($(PKG_CONFIG) gobject-introspection-1.0 --variable=girdir) -.PHONY: all-bindings $(BINDINGS) $(VDBG_FILES) +.PHONY: all-bindings $(BINDINGS) gir-bindings: $(GIR_BINDINGS) @@ -665,7 +666,9 @@ gidl-bindings: $(GIDL_BINDINGS) gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) -all-bindings: gir-bindings gidl-bindings $(vdbg_files) +all-bindings: gir-bindings gidl-bindings $(dist_vdbg_DATA) + +all-vdbgs: $(dist_vdbg_DATA) %.vdbg: %.vapi $(VAPI2DBG) $(VAPIGENFLAGS) $< -o $@ -- GitLab From fa0202e94d4fd5bbeb27671b79843ba3c095ac51 Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Sun, 24 Jul 2022 16:44:07 +0200 Subject: [PATCH 5/7] compiler: Add support for printing backtraces on signal. Depends on libvalabacktrace (https://github.com/JCWasmx86/libvalabacktrace) --- Makefile.am | 1 + ccode/valaccodefile.vala | 6 + codegen/valaccodebasemodule.vala | 35 +++- codegen/valaccodecompiler.vala | 3 +- codegen/valaccodedelegatemodule.vala | 4 + codegen/valagsignalmodule.vala | 2 + compiler/valacompiler.vala | 11 +- configure.ac | 1 + vala/Makefile.am | 1 + vala/valaassemblyemitter.vala | 50 ++++++ vala/valacodecontext.vala | 236 +++++++++++++++++++++++++++ vala/valacodenode.vala | 14 ++ vapi2dbg/.gitignore | 1 + vapi2dbg/Makefile.am | 93 +++++++++++ vapi2dbg/install_debug.sh | 5 + vapi2dbg/vapi2dbg.vala | 164 +++++++++++++++++++ 16 files changed, 615 insertions(+), 12 deletions(-) create mode 100644 vala/valaassemblyemitter.vala create mode 100644 vapi2dbg/.gitignore create mode 100644 vapi2dbg/Makefile.am create mode 100755 vapi2dbg/install_debug.sh create mode 100644 vapi2dbg/vapi2dbg.vala diff --git a/Makefile.am b/Makefile.am index 6af784f15..32b6f68a2 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 f61da07df..c49dc9fd7 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 2f0ea22d8..5afac3056 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 df2aa0d28..12eaae724 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 64ad460c3..051a64a0e 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 11389bade..0da17505c 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 13444d519..5e03e637f 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 e2e31ea37..3755f56b8 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 8f9f81cf2..d4d06270e 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 000000000..df2f0afda --- /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 63dacd1a3..7694702ff 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 3ff39dbc8..22e6d5c2e 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/vapi2dbg/.gitignore b/vapi2dbg/.gitignore new file mode 100644 index 000000000..58bcd0532 --- /dev/null +++ b/vapi2dbg/.gitignore @@ -0,0 +1 @@ +vapi2dbg diff --git a/vapi2dbg/Makefile.am b/vapi2dbg/Makefile.am new file mode 100644 index 000000000..91535cad4 --- /dev/null +++ b/vapi2dbg/Makefile.am @@ -0,0 +1,93 @@ +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/ + ./install_debug.sh $(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 000000000..4f500c852 --- /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 000000000..edd31bbd8 --- /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); + 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); + context.vapi_directories = vapi_directories; + context.gir_directories = gir_directories; + context.metadata_directories = metadata_directories; + 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 (); + } +} -- GitLab From 8177c86a03edb1f7085ddb7cd91e8fae2cb23cb6 Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Tue, 27 Dec 2022 20:45:57 +0100 Subject: [PATCH 6/7] Add my progress for autotools. Doesn't work because I don't understand autotools --- vapi/Makefile.am | 199 ++++++++++++++++++++++++++++++++++++++++++- vapi2dbg/Makefile.am | 1 - 2 files changed, 197 insertions(+), 3 deletions(-) diff --git a/vapi/Makefile.am b/vapi/Makefile.am index be1c1ff22..b09a6ca41 100644 --- a/vapi/Makefile.am +++ b/vapi/Makefile.am @@ -451,16 +451,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) + +VDBG_FILES = $(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 +660,10 @@ gidl-bindings: $(GIDL_BINDINGS) gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) -all-bindings: gir-bindings gidl-bindings +all-bindings: gir-bindings gidl-bindings $(vdbg_files) + +%.vdbg: %.vapi + $(VAPI2DBG) $< -o $@ atk: $(GENVAPI) --library $(srcdir)/atk --metadatadir $(METADATADIR) $(METADATADIR)/Atk-1.0-custom.vala $(GIRDIR)/Atk-1.0.gir diff --git a/vapi2dbg/Makefile.am b/vapi2dbg/Makefile.am index 91535cad4..bbf7d811f 100644 --- a/vapi2dbg/Makefile.am +++ b/vapi2dbg/Makefile.am @@ -83,7 +83,6 @@ CLEANFILES = \ install-exec-hook: mkdir -p $(datarootdir)/vala/debug/ - ./install_debug.sh $(datarootdir)/vala/debug/ if ENABLE_UNVERSIONED cd $(DESTDIR)$(bindir) && $(LN_S) -f vapi2dbg@PACKAGE_SUFFIX@$(EXEEXT) vapi2dbg$(EXEEXT) endif -- GitLab From f7ad891e054915e2c83de5c751ce6d4b16201ee4 Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Tue, 1 Aug 2023 19:53:27 +0200 Subject: [PATCH 7/7] Fix oopsie --- vapi/Makefile.am | 7 ------- 1 file changed, 7 deletions(-) diff --git a/vapi/Makefile.am b/vapi/Makefile.am index a77055f3b..6e34a42fe 100644 --- a/vapi/Makefile.am +++ b/vapi/Makefile.am @@ -661,19 +661,12 @@ gidl-bindings: $(GIDL_BINDINGS) gstreamer-1.0-bindings: $(GSTREAMER_1_0_BINDINGS) -<<<<<<< HEAD -all-bindings: gir-bindings gidl-bindings $(vdbg_files) - -%.vdbg: %.vapi - $(VAPI2DBG) $< -o $@ -======= all-bindings: gir-bindings gidl-bindings $(dist_vdbg_DATA) all-vdbgs: $(dist_vdbg_DATA) %.vdbg: %.vapi $(VAPI2DBG) $(VAPIGENFLAGS) $< -o $@ ->>>>>>> lw64/backtrace atk: $(GENVAPI) --library $(srcdir)/atk --metadatadir $(METADATADIR) $(METADATADIR)/Atk-1.0-custom.vala $(GIRDIR)/Atk-1.0.gir -- GitLab