Safely mixing C/C++ bindings for GNOME libraries
Hi All,
Just a quick note about a common source of build failures (e.g., bug #112274) [1].
Basically, we disable the use of deprecated GNOME library symbols wherever possible so that we can avoid big API migration projects in future. A common problem, however, is that some of the C++ bindings (e.g., glibmm and gtkmm) use some of those deprecated symbols!
In other words:
Inkscape ----> glibmm ----> deprecated stuff in glib ---> glib ---> gtkmm ----> deprecated stuff in gtk+ ---> gtk+
So, even though we don't use deprecated stuff ourselves, we still need to take a little care with this!
The solution is to ** Ensure that high-level dependencies are included in our source before low-level dependencies **
For example, the Glib::Thread API in glibmm depends on deprecated GThread stuff in glib.
We will get a build failure if we do the following...
#include <glib.h> #include <glibmm/threads.h>
This is because the deprecated GThread stuff in <glib.h> will be hidden by the C++ preprocessor. When <glibmm/threads.h> is subsequently included, GThread stuff will therefore appear to be undeclared and we get an error like this:
/usr/include/glibmm-2.4/threads.h:142:11: error: field ‘gobject_’ has incomplete type /usr/include/glibmm-2.4/glibmm/threads.h: In member function ‘GThread* Glib::Threads::Thread::gobj()’:
The solution is to do the inclusions in this order:
#include <glibmm/threads.h> #include <glib.h>
This now compiles correctly because when <glibmm/threads.h> itself includes <glib.h>, it temporarily re-enables the deprecated stuff, uses it, and then disables it again.
A couple of additional notes:
1. There's actually no need to #include <glib.h> after one of the <glibmm/*.h> headers... it is already pulled into our source by the glibmm header!
2. Remember that you have to avoid *any* inclusion on <glib.h> before using a <glibmm/*.h> header. As such, it's safest to just put the C++ headers at the top of any source file: i.e.,
// Gtkmm/Glibmm headers first... #include <gtkmm/aaa.h> #include <gtkmm/bbb.h> #include <glibmm/ccc.h> #include <glibmm/ddd.h>
// Now include Inkscape stuff... #include "ui/dialog/wibble.h" #include "ui/dialog/wobble.h"
3. Ultimately, we can probably get rid of all direct usage of <glib.h> and Gtk+ headers and replace them with their respective C++ binding headers.
Cheers,
AV
I can't compile r12347 under Windows XP: glibmm/threads.h: No such file or directory Luca
-- View this message in context: http://inkscape.13.x6.nabble.com/Safely-mixing-C-C-bindings-for-GNOME-librar... Sent from the Inkscape - Dev mailing list archive at Nabble.com.
On 2013-06-05 11:39 +0100, LucaDC wrote:
I can't compile r12347 under Windows XP: glibmm/threads.h: No such file or directory Luca
Reproduced with trunk builds of r12347 on Mac OS X 10.5.8 with older versions of glib, glibmm and gtkmm (X11 as well as Quartz backend):
CXX desktop.o In file included from ui/dialog/dock-behavior.h:16, from ui/dialog/dialog.h:17, from ui/dialog/dialog-manager.h:17, from desktop.cpp:29: ./ui/widget/dock-item.h:14:28: error: glibmm/threads.h: No such file or directory make[3]: *** [desktop.o] Error 1 make[2]: *** [all] Error 2 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2
Installed dependencies on that legacy Leopard system:
$ port installed glib2 glibmm gtkmm | grep active Warning: port definitions are more than two weeks old, consider using selfupdate glib2 @2.28.8_1+collate_with_carbon (active) glibmm @2.28.2_0 (active) gtkmm @2.24.2_0 (active) LeWitt:mp-quartz suv$
LeWitt:inkscape-dbus suv$ port installed glib2 glibmm gtkmm | grep active Warning: port definitions are more than two weeks old, consider using selfupdate glib2 @2.28.8_1+collate_with_carbon (active) glibmm @2.28.0_1 (active) gtkmm @2.24.0_0 (active) LeWitt:inkscape-dbus suv$
On Jun 5, 2013, at 11:36 AM, ~suv wrote:
On 2013-06-05 11:39 +0100, LucaDC wrote:
I can't compile r12347 under Windows XP: glibmm/threads.h: No such file or directory Luca
Reproduced with trunk builds of r12347 on Mac OS X 10.5.8 with older versions of glib, glibmm and gtkmm (X11 as well as Quartz backend):
I should have a configure.ac fix for that shortly.
On 2013-06-06 02:14 +0100, Jon Cruz wrote:
On Jun 5, 2013, at 11:36 AM, ~suv wrote:
On 2013-06-05 11:39 +0100, LucaDC wrote:
I can't compile r12347 under Windows XP: glibmm/threads.h: No such file or directory Luca
Reproduced with trunk builds of r12347 on Mac OS X 10.5.8 with older versions of glib, glibmm and gtkmm (X11 as well as Quartz backend):
I should have a configure.ac fix for that shortly.
1) Revision 12353 fails to compile with older (2.28.x) and newest (2.36.x) glib/glibmm versions (different errors):
On legacy Mac OS X 10.5.8 system with - glib 2.28.8, glibmm 2.28.2, gtkmm 2.24.2:
CXX ui/dialog/filedialog.o In file included from ui/dialog/filedialog.cpp:19: ui/dialog/filedialogimpl-gtkmm.h:24:28: error: glibmm/threads.h: No such file or directory CXX ui/dialog/filedialogimpl-gtkmm.o In file included from ui/dialog/filedialogimpl-gtkmm.cpp:24: ui/dialog/filedialogimpl-gtkmm.h:24:28: error: glibmm/threads.h: No such file or directory make[3]: *** [ui/dialog/filedialog.o] Error 1 make[3]: *** Waiting for unfinished jobs.... make[3]: *** [ui/dialog/filedialogimpl-gtkmm.o] Error 1 make[2]: *** [all] Error 2 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2
AFAICT the build failure here is due to a typo in the earlier revision (in 'src/ui/dialog/filedialogimpl-gtkmm.h' the include line had been added twice in r12347, but in r12353 only one of them is put inside the #if … #endif condition)
On up-todate OS X 10.7.5 with - glib 2.36.2, glibmm 2.36.2, gtkmm 2.24.3 (patched via MacPorts):
CXX ege-adjustment-action.o In file included from /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm.h:89, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/stockid.h:26, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/iconset.h:35, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/style.h:46, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/rc.h:31, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/widget.h:48, from ../../src/widgets/icon.h:21, from ../../src/ege-adjustment-action.cpp:45: /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm/threads.h:203: error: field ‘gobject_’ has incomplete type /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm/threads.h: In member function ‘GThread* Glib::Threads::Thread::gobj()’: /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm/threads.h:199: error: ‘gobject_’ was not declared in this scope /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm/threads.h: In member function ‘const GThread* Glib::Threads::Thread::gobj() const’: /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm/threads.h:200: error: ‘gobject_’ was not declared in this scope make[3]: *** [ege-adjustment-action.o] Error 1 make[2]: *** [all] Error 2 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2
OTOH the build of r12353 succeeds on OS X 10.7.5 with these versions: - glib 2.32.4, glibmm 2.32.1, gtk+/x11 2.24.13, gtkmm 2.24.2 - glib 2.34.3, glibmm 2.34.1, gtk+/quartz 2.24.17, gtkmm 2.24.2
2) Doesn't the new check introduced in revision 12353 [1] duplicate one already introduced in r12337 [2] for the same purpose?
3) AFAICT the latest changes in r12353 do not address includes in files compiled for optional features i.e. if ImageMagick, libcdr and libvisio are detected by configure - see also comment #10 in bug #1179338.
[1] http://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/revision/12353#configure.ac [2] http://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/revision/12337#configure.ac
On Jun 6, 2013, at 11:39 AM, ~suv wrote:
- Revision 12353 fails to compile with older (2.28.x) and newest
(2.36.x) glib/glibmm versions (different errors):
On legacy Mac OS X 10.5.8 system with
- glib 2.28.8, glibmm 2.28.2, gtkmm 2.24.2:
CXX ui/dialog/filedialog.o In file included from ui/dialog/filedialog.cpp:19: ui/dialog/filedialogimpl-gtkmm.h:24:28: error: glibmm/threads.h: No such file or directory
Fixed in a pending follow-up.
AFAICT the build failure here is due to a typo in the earlier revision (in 'src/ui/dialog/filedialogimpl-gtkmm.h' the include line had been added twice in r12347, but in r12353 only one of them is put inside the #if … #endif condition)
Yes.
On up-todate OS X 10.7.5 with
- glib 2.36.2, glibmm 2.36.2, gtkmm 2.24.3 (patched via MacPorts):
CXX ege-adjustment-action.o In file included from /Volumes/magenta/mp-trunk/quartz/include/glibmm-2.4/glibmm.h:89, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/stockid.h:26, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/iconset.h:35, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/style.h:46, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/rc.h:31, from /Volumes/magenta/mp-trunk/quartz/include/gtkmm-2.4/gtkmm/widget.h:48, from ../../src/widgets/icon.h:21, from ../../src/ege-adjustment-action.cpp:45:
The pending follow-up added missing config.h inclusion that building on an Ubuntu test system did not highlight.
OTOH the build of r12353 succeeds on OS X 10.7.5 with these versions:
- glib 2.32.4, glibmm 2.32.1, gtk+/x11 2.24.13, gtkmm 2.24.2
- glib 2.34.3, glibmm 2.34.1, gtk+/quartz 2.24.17, gtkmm 2.24.2
- Doesn't the new check introduced in revision 12353 [1] duplicate one
already introduced in r12337 [2] for the same purpose?
Not really. Its consequences are close, but the new check is explicitly verifying the presence of the newer header, versus guessing that it might be there due to version checks. (partly this is needed as glibmm does not provide any version check macros we could use for compile-time vs. configure-time checks)
In theory a later version of glibmm might drop that header file and the earlier check from 12337 would cause code to fail, while the newer HAVE_ check would keep working.
(even Microsoft has recommended doing feature checks, not version checks)
- AFAICT the latest changes in r12353 do not address includes in files
compiled for optional features i.e. if ImageMagick, libcdr and libvisio are detected by configure - see also comment #10 in bug #1179338.
Yes. Yet another follow-up can check for those... or in the meantime anyone who trips over it can have a template of successful fixup they can just copy and paste.
Rev 12358 compiled fine under Windows XP, both with devlibs45 and devlibs46 (I'm still keeping both while using the former for the slowdown problem introduced with the latter). Thanks for the fix. Luca
-- View this message in context: http://inkscape.13.x6.nabble.com/Safely-mixing-C-C-bindings-for-GNOME-librar... Sent from the Inkscape - Dev mailing list archive at Nabble.com.
Hello Alex,
I've attached a diff with re-ordered headers here: https://bugs.launchpad.net/inkscape/+bug/1181928
Getting the same build errors as previously attached.
Samuel
On Thu, May 16, 2013 at 7:32 PM, Alex Valavanis <valavanisalex@...400...> wrote:
Hi All,
Just a quick note about a common source of build failures (e.g., bug #112274) [1].
Basically, we disable the use of deprecated GNOME library symbols wherever possible so that we can avoid big API migration projects in future. A common problem, however, is that some of the C++ bindings (e.g., glibmm and gtkmm) use some of those deprecated symbols!
In other words:
Inkscape ----> glibmm ----> deprecated stuff in glib ---> glib ---> gtkmm ----> deprecated stuff in gtk+ ---> gtk+
So, even though we don't use deprecated stuff ourselves, we still need to take a little care with this!
The solution is to ** Ensure that high-level dependencies are included in our source before low-level dependencies **
For example, the Glib::Thread API in glibmm depends on deprecated GThread stuff in glib.
We will get a build failure if we do the following...
#include <glib.h> #include <glibmm/threads.h>
This is because the deprecated GThread stuff in <glib.h> will be hidden by the C++ preprocessor. When <glibmm/threads.h> is subsequently included, GThread stuff will therefore appear to be undeclared and we get an error like this:
/usr/include/glibmm-2.4/threads.h:142:11: error: field ‘gobject_’ has incomplete type /usr/include/glibmm-2.4/glibmm/threads.h: In member function ‘GThread* Glib::Threads::Thread::gobj()’:
The solution is to do the inclusions in this order:
#include <glibmm/threads.h> #include <glib.h>
This now compiles correctly because when <glibmm/threads.h> itself includes <glib.h>, it temporarily re-enables the deprecated stuff, uses it, and then disables it again.
A couple of additional notes:
- There's actually no need to #include <glib.h> after one of the
<glibmm/*.h> headers... it is already pulled into our source by the glibmm header!
- Remember that you have to avoid *any* inclusion on <glib.h> before
using a <glibmm/*.h> header. As such, it's safest to just put the C++ headers at the top of any source file: i.e.,
// Gtkmm/Glibmm headers first... #include <gtkmm/aaa.h> #include <gtkmm/bbb.h> #include <glibmm/ccc.h> #include <glibmm/ddd.h>
// Now include Inkscape stuff... #include "ui/dialog/wibble.h" #include "ui/dialog/wobble.h"
- Ultimately, we can probably get rid of all direct usage of <glib.h>
and Gtk+ headers and replace them with their respective C++ binding headers.
Cheers,
AV
[1] https://bugs.launchpad.net/inkscape/+bug/1122774
AlienVault Unified Security Management (USM) platform delivers complete security visibility with the essential security capabilities. Easily and efficiently configure, manage, and operate all of your security controls from a single console and one unified framework. Download a free trial. http://p.sf.net/sfu/alienvault_d2d _______________________________________________ Inkscape-devel mailing list Inkscape-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/inkscape-devel
participants (5)
-
Alex Valavanis
-
Jon Cruz
-
LucaDC
-
Samuel Chase
-
~suv