You are here

Tutorial : cross-compile from Linux to Windows (Vala)

Objectives : compile a Vala/GTK+ application under Linux, and produce a valid Windows© binary.

We have a Vala application using GTK+2 as its graphical toolkit :

We want to create a Windows version of it, without modifiying the source code nor having a Windows box available.

Prerequisites

A Linux Debian or Ubuntu distro, with Vala installed.

To install Vala, please read this previous article, part 1).

1) Install the compilation toolchain

- Install the GCC compiler for Windows (named MinGW) :

apt-get install mingw32

- Download GTK+ 2.24 for Windows :
gtk+-bundle_2.24.10-20120208_win32.zip (23.5 Mb)

(ps : Create a folder named "gtk-win32" where you want, put the ZIP archive therein and extract it with :
unzip gtk+-bundle_2.24.10-20120208_win32.zip)


- Adapt GTK+ to its location :
In a terminal, move to the "gtk-win32" folder you just created. If you extracted it to "/opt/gtk-win32" e.g. :
cd /opt/gtk-win32
then do :
find -name '*.pc' | while read pc; do sed -e "s@^prefix=.*@prefix=$PWD@" -i "$pc"; done

2) Compile

- We will tell "pkg-config" to locate GTK+ libraries in our custom path. If you extracted to "/opt/gtk-win32" e.g. :
export PKG_CONFIG_PATH=/opt/gtk-win32/lib/pkgconfig

We are ready ! We will use this simple source code as an example.

- Compile the example :
valac --cc=i586-mingw32msvc-gcc --pkg gtk+-2.0 -o testGTK2.exe testGTK2.vala

A new testGTK2.exe executable should have been created if everything went well.
It won't run on our Linux system, because it's targeting Windows !

3) Release

- Create a folder containing the binary and the Windows .dll files. If you extracted to "/opt/gtk-win32" e.g. :
mkdir ~/distri
cp testGTK2.exe ~/distri
cp /opt/gtk-win32/bin/*.dll ~/distri

- Here we go ! Transfer this folder to a Windows box. Double-click on the executable and...

Well done !

Comments

Hi, thank you for this, I've been wondering how to achieve this.
how would I crosscompile for Gtk3?

(originally posted by ekundayo)

Hi ekundayo,

Same thing for GTK+3, but you need to use the corresponding bundle for Windows. Grab it here, and install it on Linux using Wine. Then get the install folder (normally : $HOME/.wine/drive_c/Program Files/GTK+) and use it as I've used the GTK+2 one in this tutorial.

Thanks for the great tutorial. I use GTK+3 and follow your steps but get the following error when compiling:
/usr/lib/gcc/i586-mingw32msvc/4.2.1-sjlj/../../../../i586-mingw32msvc/bin/ld: cannot find -lX11
Any suggestions?

(originally posted by Rikard)

Hi Rikard,

You've obviously got an error in your compiler flags ; win32 doesn't use nor need libX11.

Please run "pkg-config --libs gtk+-3.0". If the output contains "-lX11", there's a problem ; you need to check that PKG_CONFIG_PATH is well defined to /opt/gtk-win32 (by doing echo $PKG_CONFIG_PATH ; ls $PKG_CONFIG_PATH). Please note that by running "export PKG_CONFIG_PATH" like written in my tutorial, it only stays active in the terminal where you typed it, so you need to re-run it in each terminal -or make it permanent by adding it to your .bashrc for instance.

I was trying to do the exact same thing and got the same results. From what I can tell my issue is caused by the valac-0.18 .vapi and .deps files for gtk+-3.0 show a dependency on x11 and use X.Window instead of Gdk.NativeWindow like gtk+-2.0 did. I tried a direct change to these files but I can't get the gtk+-3.0.vapi to recognize Gdk.NativeWindow as a valid replacement for X.Window.

Any ideas?

Wow, that's a nice one ! You're right Myrrdin, GTK+3' VAPI depends on X11 !

I don't think that's the problem, though, because removing the x11 line screws up on native Win32 too. Vala complains about missing symbols. And the VAPI is exactly the same ! Seems like something in GTK+3 itself (or GDK, or Cairo), or their .pc files, is doing platform-dependant detection.

Problem is, it could be caused by so many things, and I don't have any Linux box handy right now, so I can't help quickly.
You know what ? Please land on irc.gimp.org, channel #gtk+, and if you come I'll try to trace the problem with you.

I thank you for the offer, but after some sleep I figured out what to change. I just wish I could find the exact reason that it works.

So to get it to compile you need to remove the x11 line in the gtk+-3.0.deps file in your vapi directory.

Then you need to replace each instance of X.Window in the gtk+-3.0.vapi file, also in your vapi directory, with just the word Window. In vim this is easily done with:

:1,$s/X\.Window/Window/g

Or, however, your text editor handles replacement.

This should then allow your GTK3 application to compile and run. Now I'm not sure why Window works since it is an X11 define as far as I can tell. I would need more time to look into why this is. I believe the problems however stems from the fact that GDK is now runtime checking for available window systems (gdk explanation). My thought is currently that the person who generated the vapi only had the X11 backend and since it was auto generated by vapigen that is what we get for the vapi file itself. Of course this is mostly speculation.

Anyway, try that and it should work for you. It at least made it possible to run my application as GTK3 in wine.

Interesting ! But I think I've found a simpler -temporary- solution ;-) :
mv /usr/lib/pkgconfig/x11.pc /usr/lib/pkgconfig/x11.pc.old
compile...
mv /usr/lib/pkgconfig/x11.pc.old /usr/lib/pkgconfig/x11.pc

Explanation : gtk+-3.0 depends here on x11. It's not really used with win32, but if you are on linux, and you happen to have X11 development files installed (libx11-dev on Debian/Ubuntu), you're likely to have x11.pc somewhere.

Vala sees an "x11" dep, and tells pkg-config to try to find the corresponding "x11.pc". It it doesn't find it, work fine though. If it does... it uses it, and screws up !

A permanent solution would be yours, or simpler :
In gtk+-3.0.deps, replace "x11" with "x11lin", and copy "x11.vapi" as "x11lin.vapi". It won't try to use the .pc anymore.

When run the exe under windows system, there will be a command window displayed, how to hide it?
In https://wiki.gnome.org/Projects/Vala/ValaOnWindows, it says pass "-X -mwindows" to the valac complier,
but in Linux, when add "-X -mwindows" to valac, the compile will failed.

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.