Cross-compling Gtk to create a Windows cross-build system on Linux

Sorry if the topic is a little confusing, but it’s basically what I’m trying to do.

I’m trying to create a cross-build system on Linux (Debian) to build the Gtk3 port of VICE for Windows.
We had this working fine when we still used the native Win32 API for the Windows build, but since we dumped all native UI’s in favour of Gtk3 (Linux, BSD, Windows, MacOS) or SDL (old systems, raspberry etc) we haven’t been able to create a proper cross-build of Gtk3-Windows with openGL support. I can create Windows builds with msys2, but our nightly build system runs Linux and I’d personally also rather use Linux, I’m not a Windows fan at all.

I haven’t been able to find any proper (current) documentation on this subject, there’s plenty of documentation on building Gtk3 on Windows, but very little on compiling Gtk3 (and its dependencies) to be used in a cross-build environment.
I’ve noticed some instructions in the various source tarballs of Gtk3, GLib, etc and those will help me get along.

But my question (finally) is:

Any advice/docs on what versions of the various components to use? For example I intend to compile the latest stable Gtk (3.24.7), but what GLib version should I use as a dependency for that? Is 2.60 usable, or should I go lower? Same goes for things like Atk, Pango, Cairo, Gdk-Pixbuf and most likely others.

A final note: I know Fedora has some cross-build packages for Gtk3/GLib, but our cross-build system is Debian-based and I have no control over the nightly build server.

While you can’t use Fedora’s great mingw integration, you might take some inspiration from the packaging scripts.

In general, you’ll want the most recently released stable version of all the packages and their dependencies (within reason for your base operating system). Gtk 3.24 and GLib 2.60 if you can. From looking at the Fedora scripts, I think they are still on 3.22 for Gtk.

Thank you, those packaging scripts will prove useful.

Meanwhile I managed to cross-compile GLib for Windows, I used 2.58.3, since that’s what my MSYS2 uses on my Windows box, I’ll update to 2.60.
I had to install and use pip3 to get Meson >=0.48 to build GLib, Debian 9.6 only has Meson 0.37.

I managed to build a little Windows binary that uses g_print() to print “WinMain called”, and it’s only 400KB :slight_smile:

But I seem to be on the right track, next up are the other dependencies of Gtk3, and any openGL (GLEW) libraries I need.

Edit: I noticed a small mistake in,
meson --cross_file cross_file.txt builddir should be meson --cross-file cross_file.txt builddir (the underscore in --cross_file should be a dash: --cross-file)

Got a bit futher, I’m working on Cairo now, and I noticed Cairo’s configure mentions EGL, GLX and WGL (all optional).

My experience so far with Cairo is that it doesn’t actually use any HW rendering backend, neither on Linux, Windows or MacOS. So is there any reason to try to have Cairo build against WGL?

No. Cairo GL is not used by GTK.

Out of curiosity: when does Cairo use GL?

Never. GL is an experimental cairo backend (the same way win32 and image are backends). Unless you make explicit use of it, it won’t be used. AFAIU.


  • It’s compiled with GL support
  • You create a GL surface

In other words: you have to explicitly tell it to use the GL rendering implementation.

So it is possible to have Cairo use GL then. Should I decide to try this, can I tell Cairo at runtime to not use GL?

In VICE we see a marked increase in performance when switching from Cairo to GtkGlArea. Unfortunately GtkGlArea seems to have issues with Intel chipsets, forcing us to provide a “fallback” renderer using Cairo.

My guess would be Cairo’s GL backend would share code with GtkGlArea’s code, meaning we’d still have that issue?

A little update: I managed to cross-compile most Gtk3 dependencies, but gobject-introspection is giving me trouble:

$ meson --prefix=/opt/cross --cross-file cross_file.txt builddir

give me this:

Can not use target g-ir-compiler as a generator because it is cross-built
and no exe wrapper is defined or needs_exe_wrapper is true.
You might want to set it to native instead.

Using ./autogen + ./configure:

$ PKG_CONFIG_PATH=/opt/cross/lib/pkgconfig CPPFLAGS="-I/opt/cross/include" LDFLAGS="-L/opt/cross/lib" ./configure --prefix=/opt/cross --host=x86_64-w64-mingw32

I get:

configure: error: 'autoconf-archive' missing

While I have autocong-archive installed:

$ apt-cache policy autoconf-archive
  Installed: 20160916-1
  Candidate: 20160916-1
  Version table:
 *** 20160916-1 500
        500 stretch/main amd64 Packages
        100 /var/lib/dpkg/status

My cross_file.txt looks like this:

system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

c_args = []
c_link_args = []
native = true

c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
pkgconfig = 'x86_64-w64-mingw32-pkg-config'
windres = 'x86_64-w64-mingw32-windres'

I added the “native = true” due to meson complaining, didn’t help.

Can anyone give me some idea of what I’m doing wrong here? What is preferred: meson/ninja or autotools when cross-compiling?

Introspection data is platform and architecture specific, and it the introspection scanner needs to build a small binary to generate the data related to GObject properties, signals, hierarchies, and interfaces. It is possible to generate the introspection data when cross-compiling, as long as you have a native version of g-ir-scanner already compiled for the target platform and a wrapper, like qemu-arm-static for cross-compiling to ARM. For Windows, you’d need a way to run a whole environment, including a toolchain, so wine is not enough.

If you don’t care about introspection, you can either use -Dintrospection=false or --disable-introspection when configuring the build with Meson or Autotools, respectively.

You need autoconf-archive installed inside the path where the aclocal you use to generate the configuration script will look into; use aclocal --print-ac-dir to see where that is.

Either are fine.

Fedora has mingw cross-compiled packages for GTK, so you may want to look at their build scripts. They don’t do much, aside from setting environment variables and search paths.

I suspected gobject-introspection might require “bootstrapping” in this case. Since I don’t use it, I’ll disable it.

Good idea, I’ll have a look at those.

Thanks for the suggestions, I can continue my quest now. :slight_smile:

It looks like using Pango-1.43.0 and Meson, I need to pass -Dgir=false, not -Dintrospection=false.

I assume -D can override options in meson_options.txt, which contains:

       description: 'Build the GObject introspection data for Pango',
       type: 'boolean',
       value: true)

This makes building Pango via Meson and installing via Ninja work. (I do get quite a few warnings about "%ld expecting long int but getting long long int).


Seems to happen in pango emoji handling(?):

emoji_presentation_scanner.rl:71:13: note: in expansion of macro ‘found_emoji_presentation_sequence’
../pango/pango-emoji.c:198:21: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘long long int’ [-Wformat=]
     if (0) g_print ("emoji %ld..%ld\n", ts - buffer, te - buffer);

I’m using a 64-bit Debian VM, 64-bit mingw and my ‘cross_file.txt’ only contains references to x86_64-w64-mingw32-${tool}.

Seems like a bug to me. %ld is for 32-bit integers, %lld% is for 64-bit ones.

Yes, it is a bug. But there could be reasons for it:

GLib coding guidelines seem to indicate a preference for C89 (unless my Google-fu is off), but allow C99 for specific stuff: “We will use features beyond C89 if they are substantially useful and if they are supported in a wide range of compilers”

Which will work on basically anything but Windows. If g_print() and friends are wrappers around Windows’ libc printf() and friends, %llu, %z etc won’t work on Windows.
(Latest MSVC seems to support <stdint.h> and even bits of <inttypes.h>, but I’m not a Windows dev)

g_print() is implemented using gnulib printf on Windows. Whenever you use this implementation (directly or indirectly), you can be sure that it supports all gnu_printf format specifiers, and glib has macros for those.

You only get in trouble when you use random printf code (from msvcrt, ucrt or some 3rd-party library). Usually it’s a mess.

Alright, then the g_print() using %ld for a long long is indeed a bug. I’ll report it.

It isn’t a true bug! Pango wasn’t written for Windows. It doesn’t have work-arounds for “fake 64-bit” Windows (that OS is really 32-bit Windows with 64-bit pointers). The problem is that ptrdiff_t is long int on all sane OSes (including 32-bit Windows); but, it’s long long int on “64-bit” Windows.

I assume that those expressions can be “demoted” to (long) without losing any information.

I’ve reported the “bug” on the Pango bugtracker, I suppose any discussion about this should go there, keeping this thread on topic.

ptr_diff_t should be at least as wide as a pointer, so on sane 64-bit OS’es, it should be a long when that OS uses 64-bit for long and 32-bit for int (The Standard allows for long being just 32-bit, which I suppose serves Windows well).
I agree with just casting to long probably not causing issues, I do that myself when supporting either C89 or Windows (casting size_t to unsigned long is another ‘fix’ for windows).

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.