Wednesday, June 1, 2011

Cross-compiling gtk+ applications

I have recently cross compiled a small GTK+ application for Windows as part of a multi platform project I am working on. In this post I will try to detail how I got Eclipse and MinGW working together to produce executable files for both Linux and Windows, by just switching in Eclipse the current build configuration.

All the following instructions were executed in Arch Linux using the following software:
  • Eclipse Helios SR2 for C/C++Developers
  • MinGW 2.21
  • GTK+ 2.24
  • Windows XP (virtual machine on VirtualBox 4.0.8 OSE) with GTK+ 2.22 for testing purposes

Setting up Eclipse to compile GTK+ apps

Installing GTK+ and Eclipse
Install GTK+ libraries using your distribution's package manager. Install also the development libraries if your distribution separates GTK+ in more than one package. I installed these libraries using the following command:

# pacman -S gtk2

If your distribution doesn't provide the C/C++ version of Eclipse, don't be afraid to download the newest stable release from the Eclipse download site instead. You could also install the necessary plugins in your current installation of Eclipse, but I think it is better to have an installation per "purpose" (i.e. one for C/C++ development, one for Java development, etc.), otherwise you could end up with a very memory and processor consuming IDE. After the installation, don't forget to update Eclipse.

pkg-config
The GTK+ package comes with pkg-config configuration files to tell you which flags and libraries should be included in the command line when building GTK+ manually:

# pkg-config --cflags gtk+-2.0
-pthread -I/usr/include/gtk-2.0
-I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0
-I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0
-I/usr/include/pango-1.0 -I/usr/include/glib-2.0
-I/usr/lib/glib-2.0/include -I/usr/include/pixman-1
-I/usr/include/freetype2 -I/usr/include/libpng14

# pkg-config --libs gtk+-2.0
-pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0
-lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0
-lgdk_pixbuf-2.0 -lpng14 -lm -lcairo -lpango-1.0
-lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0
-lgthread-2.0 -lrt -lglib-2.0

In order to compile GTK+ code in Eclipse, we will insert those flags into the Eclipse environment. In the following steps we consider that you have previously created a C project in Eclipse with some GTK+ source code.

CFlags
Go to "Project -> Settings -> C/C++ General -> Paths and Symbols". Select the "GNU C" option of the "Languages" list in the "Includes" tab. Now add the include directories that we got from the first pkg-config command (the ones prefixed with "I").


Now go to "Project -> Settings -> C/C++ Build -> Settings". Select "Tool Settings -> GCC C Compiler -> Miscellaneous". Append to the text of the "Other flags" field, all the flags that precede the include directories we got in the first pkg-config command (-pthread in this case).


Libraries
In the last Dialog of the previous section, select "Tool Settings -> GCC C Linker -> Miscellaneous". Write in the "Linker flags" text field the second pkg-config command, i.e.

`pkg-config --libs gtk+-2.0`

Be sure to write correctly the "``" symbols around the command, so it could expand to the libraries and linker flags properly.


You should probably be wondering why we didn't use a pkg-config command to insert the include directories and other cflags in the previous section. This is because we want to have the code completion and definitions navigation feature of Eclipse. If we use the pkg-config command they won't work.

Testing
Now you should be able to compile and execute GTK+ code in your Eclipse C project. When compiling, be sure to use the same build configuration you used in the previous steps. If you used the default settings, this configuration should be Debug. I called mine linux-debug.

GTK+ code compilation
Executing the GTK+ application

Setting up MinGW in Eclipse to cross compile GTK+ apps

Installing MinGW and GTK+ for Windows
Install MinGW using your distribution's package manager:

# pacman -S mingw32-gcc

Be sure to install the compiler family, binutils, runtime, and win32 API. In Arch, the package mingw32-gcc depends on all needed packages (ming32-binutils, ming32-runtime and ming32-win32api). After the installation, these packages create a minimal build tree in /usr/i486-mingw32/, containing Windows versions of various standard header files and other files required to compile against Windows libraries. They also install mingw32 versions of the GNU compiler and binutils commands (gcc, cpp, as, etc.) with the same names, but prefixed with "i486-mingw32".

For you to be able to compile your GTK+ app in this build environment, the Windows GTK+ development files need to be placed there. You can get these from the GTK+ for Windows download page, where you should download the developer packages and runtimes. You could download just the libraries you need or download the all-in-one bundle. After downloading, decompress the files in /usr/i486-mingw32/.

Once they're in place, you need to execute the following commands to make sure the pkg-config files are all OK and have the correct prefixes:

# cd /usr/i486-mingw32
# sed -i 's|^prefix=.*$|prefix=/usr/i486-mingw32|g'
 lib/pkgconfig/*.pc
# cd ./lib
# for f in *.lib; do mv $f lib${f%%lib}a; done

Create a i486-mingw32-pkg-config script in your $PATH containing the following code:

#!/bin/sh

PKG_CONFIG_LIBDIR=/usr/i486-mingw32/lib/pkgconfig \
PKG_CONFIG_PATH=/usr/i486-mingw32/lib/pkgconfig \
pkg-config $*

As the MinGW packages don't come with their own version of pkg-config, this ensures that the compiler and linker are given the correct arguments for the build environment we've created. It is not mandatory to put the code on a script, but saves a lot of typing.

Finally, there is a Windows installer for the GTK+ runtime environment that you can download here. Unless you want to embed GTK+ in your application, this is the easiest way to get GTK+ apps running on Windows.

pkg-config
As before, we will use pkg-config to know which flags and libraries are necessary to compile GTK+ applications using our MinGW build environment.

# i486-mingw32-pkg-config --cflags gtk+-2.0
-mms-bitfields -I/usr/i486-mingw32/include/gtk-2.0
-I/usr/i486-mingw32/lib/gtk-2.0/include
-I/usr/i486-mingw32/include/atk-1.0
-I/usr/i486-mingw32/include/cairo
-I/usr/i486-mingw32/include/gdk-pixbuf-2.0
-I/usr/i486-mingw32/include/pango-1.0
-I/usr/i486-mingw32/include/glib-2.0
-I/usr/i486-mingw32/lib/glib-2.0/include
-I/usr/i486-mingw32/include
-I/usr/i486-mingw32/include/freetype2
-I/usr/i486-mingw32/include/libpng14

# i486-mingw32-pkg-config --libs gtk+-2.0
-L/usr/i486-mingw32/lib -lgtk-win32-2.0 -lgdk-win32-2.0
-latk-1.0 -lgio-2.0 -lpangowin32-1.0 -lgdi32
-lpangocairo-1.0 -lgdk_pixbuf-2.0 -lpango-1.0 -lcairo
-lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0
-lintl

We will also add the following flags to our configuration:
  • "-Wl,-subsystem,windows" to stop Windows launching a console every time your application is executed.
  • "-DWIN32" to allow you to change build rules for Windows in your makefiles, or to change prepossessing macros in  your C code

Eclipse configuration
To be able to switch configurations and build your code for either Linux or Windows, you need to create a new build configuration. There are several ways to do this. For example, you can go to "Project -> Settings -> C/C++ Build -> Settings", and click on "Manage Configurations". My configuration for cross compilation is called windows-release.


Strictly speaking, we should be able to cross compile by selecting MinGW as the toolchain for our new configuration in "Project -> Settings -> C/C++ Build -> Tool Chain Editor", and then insert the cflags and libraries in Eclipse as we did in the previous section. However, the way Eclipse looks for the selected toolchain files in the system seems to be hardcoded so, as far as I know, MinGW GCC toolchain can only be selected in this way in Windows.

Thus, we will use the default toolchain and make a small tweak in its configuration. First insert the cflags and libraries in the same way we did in the previous section. Then go to "Project -> Settings -> C/C++ Build -> Settings", and then to "Tool Settings -> GCC C Linker -> Miscellaneus". Append the options "-Wl,-subsystem,windows" to the text on the "Linker flags" text field.


In the same Dialog go to "Tool Settings -> GCC C Compiler -> Symbols" and add "WIN32" to the "Defined symbols" list.


Then insert the prefix "i486-mingw32-" to the text in the "Command" text field in "GCC C Compiler", "GCC C Linker", and "GCC Assembler". Finally, add "PE Windows Parser" to the parsers lists in "Binary Parsers".

Appending i486-mingw32- to gcc

Adding PE Windows binary parser

Testing
Now you should be able to build applications for Windows by selecting the appropriate build configuration in Eclipse. To test your application, just transfer it to windows and execute it. If the result file of your building doesn't have the "exe" extension, you can configure Eclipse to add it in "Project -> Settings -> C/C++ Build -> Settings -> Build Artifact".

Successful cross compilation

Execution in Windows

References and final remarks

I mostly used the following pages to create this post:
In the MinGW installation section, I textually added  some fragments of the previous references instead of using its links for the sake of clarity. The GTK+ source code I used is based on the GTK+ official tutorial Hello World application, and the examples found here.

Finally, note that you can cross compile non GTK+ applications following the instructions we explained. You'd just need to add the appropriate Windows libraries to the MinGW build environment, and add the needed flags and libraries to Eclipse as we did with GTK+.

Setting up Quartus II v8.1 under Ubuntu 8.04

When I was about to write a post about a project I'm working on, I remembered that about a two years ago I wrote a tutorial on how to setup Quartus II under Ubuntu using only Quartus' evaluation version; i.e. full board programming for free (no cracking nor hacking any software).

You can find the tutorial here. It's a little bit outdated, but the general idea should still work.

P.S.
By the way, when I was looking for the link of the tutorial I noticed that a user of the Ubuntu Documentation Community made some updates. Thanks to j.eng for his (her?) contributions.

Tuesday, May 31, 2011

We are just sculptors

I was watching Eddie Murphy's episode of Inside the Actors Studio, and I loved the quote he wrote at the age of sixteen for his yearbook:

"In reality all men are sculptors, constantly chipping away the unwanted parts of their lives trying to create their idea of the masterpiece"

Update.
Unfortunately, the video was removed from Youtube. You can find information about this episode on IMDb.

Warrior-scholars and Scholar-Warriors

I was reading an older post on Jimmac's blog, and by traversing its links I found a cool quote in this post that remind me a discussion I had with some of my classmates:

...
2,500 years ago, a Greek writer told us something about creating software: Thucydides wrote, “The society that separates its scholars from its warriors will have its thinking done by cowards and its fighting by fools.”
...

Currently I am about to finish my M.S. in Computer Science. My research area is Computational and Discrete Geometry. During my master studies I've met a lot of mathematicians (students and professors) which avoid any engineering related knowledge. Some of them even look down on engineers or, afraid of not being taken seriously, have forsaken and are reluctant to accept their engineering background.

I got my B.S. on Computer Engineering (i.e. I am an engineer) and have found no substantial difference between my and my classmates' capacity for solving geometric problems or designing algorithms. The obvious difference is my lack of background on some topics and my lack of experience in mathematical writing. However, when I talked about this with my advisor, he told me that among the best of his students were a couple of engineers, that I should not worry about that, and that I just have to work a little bit harder on those matters.

It is well known among computer engineers and discrete mathematicians that the best results in both fields comes from multi-discipline (here you can find a very interesting discussion about this matter in computational geometry). I even found very recently that the computer engineer-scientist is a very valuable profile in companies such as Facebook, Google or Cisco, and also found some success stories about this approach in a very recent research field called Human Computation (google on ReCaptcha or Gwap for some cool Human Computation projects).

When I worked together with some foreign researchers, I found that because of my background, I could propose a very different insight into problems that turned out to be very useful. I think, as Thucydides suggests, that the best results will be achieved when we decide (or not be reluctant) to mix different fields of knowledge. I strongly believe that, as long as we embrace the scholar-warrior (or warrior-scholar) profile, we will be able to solve more difficult and interesting problems in the future.