GTK4 Hello World (Circular Package References Problem)

Out of curiosity, I wanted to try an write a hello world program using GTK4 in Linux.

I used this command to generate Ada specification files:

g++ -c -fdump-ada-spec -C /usr/include/gtk-4.0/gtk/gtk.h -I /usr/include/gtk-4.0/ -I /usr/include/glib-2.0/ -I /usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I /usr/include/cairo/ -I /usr/include/pango-1.0 -I /usr/include/harfbuzz/ -I /usr/include/gdk-pixbuf-2.0/ -I /usr/include/graphene-1.0/ -I /usr/lib/x86_64-linux-gnu/graphene-1.0/include/

The trouble is there are numerous circular dependencies. I have spent many hours trying to add “limited with” to break the loops only to find that I have missing symbol errors.

Here’s the example program (does nothing yet):

with gtk_4_0_gtk_gtk_h;
with gtk_4_0_gtk_gtkmain_h;

procedure hello is
begin
  null;
end hello;

Here’s the output after a few iterations of fixing errors in the generated spec files:

gnatmake hello.adb 
x86_64-linux-gnu-gcc-12 -c hello.adb
pango_1_0_pango_pango_types_h.ads:12:09: error: circular dependency caused by with_clauses
pango_1_0_pango_pango_types_h.ads:12:09: error: possibly missing limited_with clause in one of the following
pango_1_0_pango_pango_types_h.ads:12:09: error: unit "hello (body)"
pango_1_0_pango_pango_types_h.ads:12:09: error: unit "gtk_4_0_gtk_gtkmain_h (spec)"
pango_1_0_pango_pango_types_h.ads:12:09: error: unit "pango_1_0_pango_pango_types_h (spec)"
pango_1_0_pango_pango_types_h.ads:12:09: error: unit "pango_1_0_pango_pango_font_h (spec)"
pango_1_0_pango_pango_break_h.ads:114:53: error: "PangoAnalysis" not declared in "pango_1_0_pango_pango_item_h"
pango_1_0_pango_pango_break_h.ads:115:51: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_break_h.ads:125:54: error: "PangoLanguage" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_break_h.ads:126:51: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_break_h.ads:135:53: error: "PangoAnalysis" not declared in "pango_1_0_pango_pango_item_h"
pango_1_0_pango_pango_break_h.ads:136:51: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_break_h.ads:145:53: error: "PangoAnalysis" not declared in "pango_1_0_pango_pango_item_h"
pango_1_0_pango_pango_break_h.ads:147:51: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_break_h.ads:156:60: error: "PangoAttrList" not declared in "pango_1_0_pango_pango_attributes_h"
pango_1_0_pango_pango_break_h.ads:158:51: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_gravity_h.ads:127:98: error: "PangoMatrix" not declared in "pango_1_0_pango_pango_matrix_h"
pango_1_0_pango_pango_script_h.ads:461:112: error: "PangoLanguage" not declared in "pango_1_0_pango_pango_types_h"
glib_2_0_gobject_gobject_h.ads:265:49: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:283:49: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:409:59: error: "GSList" not declared in "glib_2_0_glib_gslist_h"
glib_2_0_gobject_gobject_h.ads:418:52: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:423:52: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:430:96: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:456:47: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:485:47: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:490:165: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:516:134: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:521:182: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:554:52: error: "GParameter" not declared in "glib_2_0_gobject_gparam_h"
glib_2_0_gobject_gobject_h.ads:651:105: error: "GParamSpec" not declared in "glib_2_0_gobject_gparam_h"
pango_1_0_pango_pango_coverage_h.ads:140:70: error: "GList" not declared in "glib_2_0_glib_glist_h"
pango_1_0_pango_pango_coverage_h.ads:142:72: error: "GSList" not declared in "glib_2_0_glib_gslist_h"
pango_1_0_pango_pango_coverage_h.ads:144:72: error: "GQueue" not declared in "glib_2_0_glib_gqueue_h"
pango_1_0_pango_pango_engine_h.ads:189:56: error: "PangoEngineLang" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:192:55: error: "PangoAnalysis" not declared in "pango_1_0_pango_pango_item_h"
pango_1_0_pango_pango_engine_h.ads:193:56: error: "PangoLogAttr" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:268:56: error: "PangoEngineShape" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:269:56: error: "PangoFont" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:272:64: error: "PangoAnalysis" not declared in "pango_1_0_pango_pango_item_h"
pango_1_0_pango_pango_engine_h.ads:273:56: error: "PangoGlyphString" not declared in "pango_1_0_pango_pango_glyph_h"
pango_1_0_pango_pango_engine_h.ads:277:56: error: "PangoEngineShape" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:278:56: error: "PangoFont" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:279:56: error: "PangoLanguage" not declared in "pango_1_0_pango_pango_types_h"
pango_1_0_pango_pango_engine_h.ads:370:80: error: "GTypeModule" not declared in "glib_2_0_gobject_gtypemodule_h"
compilation abandoned
gnatmake: "hello.adb" compilation error

After adding more “limited” to the “with” package refererences I got to this point:

gnatmake hello.adb 
x86_64-linux-gnu-gcc-12 -c hello.adb
hello.adb:2:06: error: circular unit dependency
hello.adb:2:06: error: "hello (body)" depends on "gtk_4_0_gtk_gtkmain_h (spec)"
hello.adb:2:06: error: "gtk_4_0_gtk_gtkmain_h (spec)" depends on "pango_1_0_pango_pango_types_h (spec)"
hello.adb:2:06: error: "pango_1_0_pango_pango_types_h (spec)" depends on "pango_1_0_pango_pango_break_h (spec)"
hello.adb:2:06: error: "pango_1_0_pango_pango_break_h (spec)" depends on "pango_1_0_pango_pango_item_h (spec)"
hello.adb:2:06: error: "pango_1_0_pango_pango_item_h (spec)" depends on "glib_2_0_gobject_gtype_h (spec)"
hello.adb:2:06: error: "glib_2_0_gobject_gtype_h (spec)" depends on "glib_2_0_gobject_gvalue_h (spec)"
hello.adb:2:06: error: "glib_2_0_gobject_gvalue_h (spec)" depends on "glib_2_0_gobject_gtype_h (spec)"
hello.adb:2:06: error: "glib_2_0_gobject_gtype_h (spec)" depends on "glib_2_0_gobject_gtype_h (spec)"
gnatmake: "hello.adb" compilation error

Is there a foolproof method for creating bindings to a highly coupled library like GTK4?

Have you successfully created and used any other bindings?

The generated bindings aren’t usually complete, but they will at least build without modification unless they weren’t properly generated (in my experience running MacOS aarch-64 with gcc-14.1.0-aarch64 and Alire).

  1. I usually configure and build a project for my platform before I try to generate bindings for it.

I guess you already have GTK4 installed–I haven’t tried that approach. I always start by git cloneing the library I want to use, and using the header files from there. It might not affect the outcome, but it makes it easier for me to keep track of what’s going on during the process.

  1. Instead of g++ -c -fdump-ada-spec -C, try gcc -c -fdump-ada-spec followed by the include-paths (with no space between -I and each include path) and put the /usr/include/gtk-4.0/gtk/gtk.h path last. I don’t think it’s supposed to be generating bindings for Pango and the other dependencies–the -I / may be causing trouble.

  2. As for the circular references–the header gtk.h already includes gtkmain.h, so you probably don’t want to with gtk_4_0_gtk_gtkmain_h; once you get your bindings properly generated.