Search code examples
gccvalamingw-w64

Compile Vala from Linux for Windows


I usually only code in high level code so I have no experience at all compiling code (as the IDE usually does this for me) so I could be overlooking something very obvious. I've spent a lot of time figuring out how to compile Vala in Linux but I don't seem to be able to make this work.

These are the steps I took:

  1. I installed valac, gtk, mingw64 (I've built a docker image just to make sure: 0620731/valac:mingw64)
  2. Copied some working vala code from a gnome tutorial showing off gtk3.
  3. Ran this: valac --cc=x86_64-w64-mingw32-gcc-win32 --pkg gtk+-3.0 -X -mwindows ../main.vala (I tried different compilers too. Results varied, but nothing good.)

The output I got was:

In file included from /usr/lib/x86_64-linux-gnu/glib-2.0/include/glibconfig.h:9:0,
                 from /usr/include/glib-2.0/glib/gtypes.h:32,
                 from /usr/include/glib-2.0/glib/galloca.h:32,
                 from /usr/include/glib-2.0/glib.h:30,
                 from /home/developer/vala/Documents/Projects/gamedev/vala-test/bin/main.vala.c:6:
/usr/include/glib-2.0/glib/gtypes.h: In function '_GLIB_CHECKED_ADD_U64':
/usr/include/glib-2.0/glib/gmacros.h:241:53: error: size of array '_GStaticAssertCompileTimeAssertion_0' is negative
 #define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
                                                     ^
/usr/include/glib-2.0/glib/gmacros.h:238:47: note: in definition of macro 'G_PASTE_ARGS'
 #define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
                                               ^~~~~~~~~~~
/usr/include/glib-2.0/glib/gmacros.h:241:44: note: in expansion of macro 'G_PASTE'
 #define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
                                            ^~~~~~~
/usr/include/glib-2.0/glib/gtypes.h:423:3: note: in expansion of macro 'G_STATIC_ASSERT'
   G_STATIC_ASSERT(sizeof (unsigned long long) == sizeof (guint64));
   ^~~~~~~~~~~~~~~
In file included from /usr/include/glib-2.0/gio/gio.h:46:0,
                 from /usr/include/gtk-3.0/gdk/gdkapplaunchcontext.h:28,
                 from /usr/include/gtk-3.0/gdk/gdk.h:32,
                 from /usr/include/gtk-3.0/gtk/gtk.h:30,
                 from /home/developer/vala/Documents/Projects/gamedev/vala-test/bin/main.vala.c:10:
/usr/include/glib-2.0/gio/gcredentials.h: At top level:
/usr/include/glib-2.0/gio/gcredentials.h:75:1: error: unknown type name 'uid_t'
 uid_t            g_credentials_get_unix_user      (GCredentials    *credentials,
 ^~~~~
/usr/include/glib-2.0/gio/gcredentials.h:79:52: error: unknown type name 'uid_t'; did you mean 'pid_t'?
                                                    uid_t           uid,
                                                    ^~~~~
                                                    pid_t
error: cc exited with status 256
Compilation failed: 1 error(s), 0 warning(s)

I also tried compiling the c file but I got the exact same results, so it's not a buggy version.

I managed to compile the same project on Windows though, so not all is lost, but I really want to be able to do this without a dual-boot/VM. I'm so close, I don't want to quit this now.

This might be usefull (main.vala):

using Gtk;

int main(string[] args) {
    Gtk.init(ref args);

    var window = new Window();
    window.title = "First GTK+ Program";
    window.border_width = 10;
    window.window_position = WindowPosition.CENTER;
    window.set_default_size(350, 70);
    window.destroy.connect(Gtk.main_quit);

    var button = new Button.with_label("Click me!");
    button.clicked.connect(() => {
        button.label = "Thank you";
    });

    window.add(button);
    window.show_all();

    Gtk.main();
    return 0;
}

Solution

  • This is a problem with the libraries used. /usr/lib/x86_64-linux-gnu/ and /usr/include/ are the paths for native libraries. The pkg-config tool sorts this out for you. So when calling valac also pass the right pkg-config:

    valac --cc x86_64-w64-mingw32-gcc-win32 \
          --pkg-config x86_64-w64-mingw32-pkg-config \
          --pkg gtk+-3.0 \
          -X -mwindows \
          ../main.vala
    

    The next step is then make sure you have cross-compiled libraries installed on your Linux machine. It will depend on the Linux distribution you are using, for example with Fedora you will likely need to install:

    dnf install mingw64-gtk3 mingw64-glib2
    

    Finally, to make things easier to distribute, you may want to try static linking so everything is lumped together in one big binary. In Fedora there is a glib2-static package, but the problem is there doesn't seem to be static builds for GTK3. Otherwise take a look at How to distribute a GTK+ application on Windows? for some tips on the dynamic libraries you need to package.

    Unfortunately none of this is tested - I don't have Windows to try this. It would be great to have a working procedure for cross-compiling Vala applications to run on Windows. Thanks for putting the effort in to get this far and it would be useful to know if you get it working.