Cross Compiling GTK applications For the Raspberry Pi

In this blog entry I will cover how I was able to cross compile GTK+ 3.0 applications for the Raspberry Pi. I will be assuming that you are running a Debian/Ubuntu flavored Linux distribution on your PC. I was successfully able to cross compile GTK+ 3.0 applications on my PC under both CrashBang Linux 11(Debian based) & Kubuntu 12.04 (Ubuntu based) . The sample code and makefile discussed in this blog entry are available here.

Figure 1. Simple Cross compiled GTK3 application running on the RPi

Figure 1. Simple Cross compiled GTK3 application running on the RPi

I was not able to set up “pkg-config” properly for cross compilation. Instead I’m using a makefile that lists all of the necessary include and library files/directories as well as the library dependency directories. Some of the GTK+ related libraries also required that the libc.so.6 library (and a bunch of others) be placed in a specific static directory (/lib/arm-linux-gnueabihf) . I got around that by creating two soft links; one in the /lib & one in the /usr/lib directories. So this approach may be considered a bit of hack, but it works very well. I’m also using the latest Raspbian OS image on my RPi (2013-07-26 && 2013-05-25 work fine)  and suggest that you do the same.

  • Install the Raspbian OS on an SD Card
  • Plug the SD Card into the Raspberry Pi
  • Connect the Raspberry Pi to the Network and power it
  • SSH into the RPi.
  • Configure the RPi using the raspi-config utility
  • Update all packages on the RPi with the “sudo apt-get update && sudo apt-get upgrade” commands.

The first six steps listed above are covered in detail here.

  • Create a $HOME/rpi directory on your Linux PC. Download the cross-compiling toolchain for the RPi into that directory on your Linux PC and add it’s bin directory  to the PATH variable as instructed here .
  • Now log in remotely onto the RPi via an SSH connection and type: “sudo apt-get install libgtk-3-dev“. This will install the gtk3 libraries and utilities necessary onto the RPi’s SD card.
  • Turn OFF the RPi board, remove the SD card and plug it back into the Linux PC.
  • Copy the /usr and /lib directories from the SD card (root file system partition) into the $HOME/rpi/ on the Linux PC. You can use the graphical file manager or the cp command.
  • Plug the SD card back into the RPi, connect it to the network and turn it on.
  • On the Linux PC, create two soft links in the /lib && /usr/lib directories :
    • sudo ln -s  $HOME/rpi/usr/lib/arm-linux-gnueabihf/ /usr/lib/arm-linux-gnueabihf
    • sudo ln -s $HOME/rpi/lib/arm-linux-gnueabihf/ /lib/arm-linux-gnueabihf
  • Verify that the directory soft links indeed exist with the following two commands:
    • ls -ld /lib/arm-linux-gnueabihf
    • ls -ld /usr/lib/arm-linux-gnueabihf
  • Download and extract the sample code and makefile  available here.
  • The code and makefile are shown below for reference:

gtktest.c

#include <gtk/gtk.h>

gint count = 0;
char buf[5];

void increase(GtkWidget *widget, gpointer label)
{
  count++;

  sprintf(buf, "%d", count);
  gtk_label_set_text(GTK_LABEL(label), buf);
}

void decrease(GtkWidget *widget, gpointer label)
{
  count--;

  sprintf(buf, "%d", count);
  gtk_label_set_text(GTK_LABEL(label), buf);
}

int main(int argc, char** argv) {

  GtkWidget *label;
  GtkWidget *window;
  GtkWidget *frame;
  GtkWidget *plus;
  GtkWidget *minus;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 250, 180);
  gtk_window_set_title(GTK_WINDOW(window), "+-");

  frame = gtk_fixed_new();
  gtk_container_add(GTK_CONTAINER(window), frame);

  plus = gtk_button_new_with_label("+");
  gtk_widget_set_size_request(plus, 80, 35);
  gtk_fixed_put(GTK_FIXED(frame), plus, 50, 20);

  minus = gtk_button_new_with_label("-");
  gtk_widget_set_size_request(minus, 80, 35);
  gtk_fixed_put(GTK_FIXED(frame), minus, 50, 80);

  label = gtk_label_new("0");
  gtk_fixed_put(GTK_FIXED(frame), label, 190, 58); 

  gtk_widget_show_all(window);

  g_signal_connect(window, "destroy",
      G_CALLBACK (gtk_main_quit), NULL);

  g_signal_connect(plus, "clicked", 
      G_CALLBACK(increase), label);

  g_signal_connect(minus, "clicked", 
      G_CALLBACK(decrease), label);

  gtk_main();

  return 0;
}

Makefile

ARM_PREFIX= arm-linux-gnueabihf-
CC   = $(ARM_PREFIX)gcc
SRC += gtktest.c
TARGET = gtktest

LIBRARY += gtk-3 
LIBRARY += gdk-3 
LIBRARY += atk-1.0 
LIBRARY += gio-2.0 
LIBRARY += pangocairo-1.0 
LIBRARY += gdk_pixbuf-2.0 
LIBRARY += cairo-gobject 
LIBRARY += pango-1.0 
LIBRARY += cairo 
LIBRARY += gobject-2.0 
LIBRARY += glib-2.0 

LIBRARYDIR += $(HOME)/rpi/lib/arm-linux-gnueabihf 
LIBRARYDIR += $(HOME)/rpi/usr/lib/arm-linux-gnueabihf 
LIBRARYDIR += $(HOME)/rpi/lib
LIBRARYDIR += $(HOME)/rpi/usr/lib

XLINK_LIBDIR += $(HOME)/rpi/lib/arm-linux-gnueabihf 
XLINK_LIBDIR += $(HOME)/rpi/usr/lib/arm-linux-gnueabihf

INCLUDEDIR += $(HOME)/rpi/usr/include/gtk-3.0 
INCLUDEDIR += $(HOME)/rpi/usr/include/pango-1.0 
INCLUDEDIR += $(HOME)/rpi/usr/include/gio-unix-2.0/ 
INCLUDEDIR += $(HOME)/rpi/usr/include/atk-1.0 
INCLUDEDIR += $(HOME)/rpi/usr/include/cairo 
INCLUDEDIR += $(HOME)/rpi/usr/include/gdk-pixbuf-2.0 
INCLUDEDIR += $(HOME)/rpi/usr/include/freetype2 
INCLUDEDIR += $(HOME)/rpi/usr/include/glib-2.0 
INCLUDEDIR += $(HOME)/rpi/usr/lib/arm-linux-gnueabihf/glib-2.0/include 
INCLUDEDIR += $(HOME)/rpi/usr/include/pixman-1 
INCLUDEDIR += $(HOME)/rpi/usr/include/libpng12

OPT = -O0
DEBUG = -g
WARN= -Wall 
PTHREAD= -pthread

INCDIR  = $(patsubst %,-I%,$(INCLUDEDIR))
LIBDIR  = $(patsubst %,-L%,$(LIBRARYDIR))
LIB    = $(patsubst %,-l%,$(LIBRARY))
XLINKDIR = $(patsubst %,-Xlinker -rpath-link=%,$(XLINK_LIBDIR))

all:
	$(CC) $(OPT) $(DEBUG) $(WARN) $(LIBDIR) $(PTHREAD) $(INCDIR) $(XLINKDIR) $(LIB) $(SRC) -o $(TARGET)

clean:
	rm -rf $(TARGET)
  • In a terminal window on your Linux PC navigate into the “gtktest” directory, “cd ~/gtktest” and run “make“.
  • If everything went well you should end up with a binary compiled for arm called “gtktest”. Type the following command in the terminal “file gtktest“. The output should be: gtktest: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x72cb5773b65f1dce50358edfebd8be2d44aef967, not stripped.”
  • Copy the arm binary from the Linux PC to the  “home/pi/” directory on the RPi using scp. i.e. Run the following command in a terminal window on your Linux PC “scp $HOME/gtktest/gtktest  pi@10.42.0.73:/home/pi” (replace 10.42.0.73 with the IP address of your RPi). You will be prompted for the a password to connect to the RPi (user pi). It should be “raspberry” unless it was changed.
  • To test the binary on the RPi we will need to start a VNC server on the RPi and connect to it with a VNC client on your Linux PC. Detailed instructions are provided here.
  • Once the VNC session is started, and you can access the RPi’s desktop, open an LXTerminal window and type: “chmod +x gtktest” to make the gtktest binary executable and run it with “./gtktest“.
  • I got the example code from Zetcode’s GTK+ tutorial. I was able to build a few other GTK+ 3.0 examples as well.
  • You can use Eclipse as an IDE if you really want to. Simply move the gtktest directory into your eclipse workspace directory, start eclipse and when creating a new project, choose the “Makefile project with Existing Code” option.
  • Instead of using a VNC server to execute the GUI application remotely on the RPi, you can try X11 forwarding in SSH. I haven’t covered this topic yet but intend to do so in the near future.

 

This entry was posted in Raspberry Pi, Raspberry Pi Cross Development. Bookmark the permalink.

12 Responses to Cross Compiling GTK applications For the Raspberry Pi

  1. Pingback: Cross Compiling GTK applications For the Raspberry Pi « adafruit industries blog

  2. JASON says:

    thank you very much for your tutorial;

    I have finished the last two tutorials, and succeeded, it seems there are some problems in this, and I am confused.

    I followed the steps successfully until the step “In a terminal window on your Linux PC navigate into the “gtktest” directory, “cd ~/gtktest” and run “make“.”

    by the way, the Makefile and gtktest is directly downloaded from the link you give.

    I typed “make” and there are so many errors, mainly about the parameters not been defined as shown below:
    arm-linux-gnueabihf-gcc -O0 -g -Wall -L/home/huang87975716/rpi/lib/arm-linux-gnueabihf -L/home/huang87975716/rpi/usr/lib/arm-linux-gnueabihf -L/home/huang87975716/rpi/lib -L/home/huang87975716/rpi/usr/lib -pthread -I/home/huang87975716/rpi/usr/include/gtk-3.0 -I/home/huang87975716/rpi/usr/include/pango-1.0 -I/home/huang87975716/rpi/usr/include/gio-unix-2.0/ -I/home/huang87975716/rpi/usr/include/atk-1.0 -I/home/huang87975716/rpi/usr/include/cairo -I/home/huang87975716/rpi/usr/include/gdk-pixbuf-2.0 -I/home/huang87975716/rpi/usr/include/freetype2 -I/home/huang87975716/rpi/usr/include/glib-2.0 -I/home/huang87975716/rpi/usr/lib/arm-linux-gnueabihf/glib-2.0/include -I/home/huang87975716/rpi/usr/include/pixman-1 -I/home/huang87975716/rpi/usr/include/libpng12 -Xlinker -rpath-link=/home/huang87975716/rpi/lib/arm-linux-gnueabihf -Xlinker -rpath-link=/home/huang87975716/rpi/usr/lib/arm-linux-gnueabihf -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0 gtktest.c -o gtktest
    /tmp/ccrmziNY.o: In function `increase’:
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `gtk_label_get_type’
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `gtk_label_set_text’
    /tmp/ccrmziNY.o: In function `decrease’:
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `gtk_label_get_type’
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `gtk_label_set_text’
    /tmp/ccrmziNY.o: In function `main’:
    /home/huang87975716/gtktest/gtktest.c:30: undefined reference to `gtk_init’
    /home/huang87975716/gtktest/gtktest.c:32: undefined reference to `gtk_window_new’
    /home/huang87975716/gtktest/gtktest.c:33: undefined reference to `gtk_window_get_type’
    /home/huang87975716/gtktest/gtktest.c:33: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:33: undefined reference to `gtk_window_set_position’
    /home/huang87975716/gtktest/gtktest.c:34: undefined reference to `gtk_window_get_type’
    /home/huang87975716/gtktest/gtktest.c:34: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:34: undefined reference to `gtk_window_set_default_size’
    /home/huang87975716/gtktest/gtktest.c:35: undefined reference to `gtk_window_get_type’
    /home/huang87975716/gtktest/gtktest.c:35: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:35: undefined reference to `gtk_window_set_title’
    /home/huang87975716/gtktest/gtktest.c:37: undefined reference to `gtk_fixed_new’
    /home/huang87975716/gtktest/gtktest.c:38: undefined reference to `gtk_container_get_type’
    /home/huang87975716/gtktest/gtktest.c:38: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:38: undefined reference to `gtk_container_add’
    /home/huang87975716/gtktest/gtktest.c:40: undefined reference to `gtk_button_new_with_label’
    /home/huang87975716/gtktest/gtktest.c:41: undefined reference to `gtk_widget_set_size_request’
    /home/huang87975716/gtktest/gtktest.c:42: undefined reference to `gtk_fixed_get_type’
    /home/huang87975716/gtktest/gtktest.c:42: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:42: undefined reference to `gtk_fixed_put’
    /home/huang87975716/gtktest/gtktest.c:44: undefined reference to `gtk_button_new_with_label’
    /home/huang87975716/gtktest/gtktest.c:45: undefined reference to `gtk_widget_set_size_request’
    /home/huang87975716/gtktest/gtktest.c:46: undefined reference to `gtk_fixed_get_type’
    /home/huang87975716/gtktest/gtktest.c:46: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:46: undefined reference to `gtk_fixed_put’
    /home/huang87975716/gtktest/gtktest.c:48: undefined reference to `gtk_label_new’
    /home/huang87975716/gtktest/gtktest.c:49: undefined reference to `gtk_fixed_get_type’
    /home/huang87975716/gtktest/gtktest.c:49: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:49: undefined reference to `gtk_fixed_put’
    /home/huang87975716/gtktest/gtktest.c:51: undefined reference to `gtk_widget_show_all’
    /home/huang87975716/gtktest/gtktest.c:53: undefined reference to `gtk_main_quit’
    /home/huang87975716/gtktest/gtktest.c:53: undefined reference to `gtk_main_quit’
    /home/huang87975716/gtktest/gtktest.c:53: undefined reference to `g_signal_connect_data’
    /home/huang87975716/gtktest/gtktest.c:56: undefined reference to `g_signal_connect_data’
    /home/huang87975716/gtktest/gtktest.c:59: undefined reference to `g_signal_connect_data’
    /home/huang87975716/gtktest/gtktest.c:62: undefined reference to `gtk_main’
    collect2: error: ld returned 1 exit status
    make: *** [all] Error 1

    I am a Chinese and new to Linux, I try to figure out the problem but with no result, and I know little about Makefile, so please help me about this.

    and I want to translate your tutorials about raspberry into Chinese to get more Chinese like me to learn from you. I want your permission!

    my gmail is: the.jason.cn@gmail.com, looking forward for your reply.

    Thanks for your reply.

  3. halherta says:

    Jason,
    I’ll retry this and let you know how it went. Which version of Raspbian are you using on the Raspberry Pi (I was using the 05-25-2013 version I believe a newer version has been released)? and which Linux Distro are you using on the PC ?

    BTW feel free to translate my blog to Chinese, but please link it to my site. Thanks!

    • halherta says:

      Jason, I tried the tutorial with the latest Raspbian OS (2013-07-26) image. Everything worked just fine. Did you copy the /usr and /lib directories from SD card to /rpi directory on Linux PC after installing libgtk3-dev on SD card? Check the size of the ~/rpi/usr and ~/rpi/lib directories on your Linux PC. The first should be at least 1.1GB and the second at least 46.1MB.

  4. Sanjay says:

    Thank you for the tutorial.

    Perhaps I have missed a step or two, but when I run make, I keep getting error on my Ubuntu 12.04 machine that:
    gtktest.c:2.21: fatal error: gtk/gtk.h: No such file or directory
    compilation terminated
    make: *** [all] Error 1

    Where did I go wrong?

    Thanks

    • halherta says:

      this basically means that the compiler is unable to find gtk/gtk.h….so the /usr directory on the RPi was not copied properly to ~/rpi/usr/. Can you verify the size of ~/rpi/usr & ~/rpi/lib directories on your Linux PC/VM?

  5. Sanjay says:

    The size of ~/rpi/usr is 1.3G and ~/rpi/lib is 50M on Linux VM and the same on Raspberry Pi (of /usr and /lib). I ran command on linux VM sudo find / -name gtk.h and sudo find / -name gdk.h, and I got response as:
    /home/sanjay/rpi/usr/include/gtk-3.0/gtk/gtk.h and
    /home/sanjay/rpi/usr/include/gtk-3.0/gdk/gdk.h
    Which means that the gtk/gtk.h file does exist. Any thoughts?

    Thanks

    • halherta says:

      Sanjay,
      This means that the cross-compiler can’t find the gtk.h…but if you look at the makefile you’ll notice that all the appropriate #include directories are included…..

      basically the makefile includes all libraries and library directories that related to the necessary libraries. The exact list can be found by running on the Rpi: echo `pkg-config –libs gtk+-3.0`. The makefile also includes all the necessary #include directories required to build gtk3 apps, which can be discovered by running on the Rpi: echo `pkg-config –cflags gtk+-3.0`.

      This is probably a trivial error of somesort…..are there any errors (due to copying & pasting) in the make file & source file? (you could just download the files…a link is provided) Did you install the described toolchain in the tutorial and include its bin directory in the path variable via .bashrc? I recommend that you retrace all the steps. If you still can’t get it to work…Send me a detailed transcript of exactly what you did…what version of Raspbian you are using e.t.c and with more detailed info, hopefully I can help you make it work.

  6. Jason says:

    Hi, first of all happy new year and thanks again.

    I am using 2013-09-25-wheezy-raspbian, and the size of the ~/rpi/usr and ~/rpi/lib are still a bit larger than 1.1GB and 50MB,

    I have copied the folder usr and lib to the $HOME/rpi:
    ~/rpi$ ls
    lib README(hjj) README(hjj)~ tools-master usr

    what’s more,

    these are the results of running
    “ls -ld /lib/arm-linux-gnueabihf
    ls -ld /usr/lib/arm-linux-gnueabihf”

    lrwxrwxrwx 1 root root 48 Aug 25 19:43 /lib/arm-linux-gnueabihf -> /home/huang87975716/rpi/lib/arm-linux-gnueabihf/

    lrwxrwxrwx 1 root root 52 Aug 25 19:43 /usr/lib/arm-linux-gnueabihf -> /home/huang87975716/rpi/usr/lib/arm-linux-gnueabihf/

    and I am using the ubuntu 12.10 in the VMware on my PC.

    Everything seems fine but still the same error :
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `gtk_label_get_type’
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:11: undefined reference to `gtk_label_set_text’
    /tmp/ccduZmMZ.o: In function `decrease’:
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `gtk_label_get_type’
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `g_type_check_instance_cast’
    /home/huang87975716/gtktest/gtktest.c:19: undefined reference to `gtk_label_set_text’
    /tmp/ccduZmMZ.o: In function `main’:
    /home/huang87975716/gtktest/gtktest.c:30: undefined reference to `gtk_init’

    it seems that the file could not found all the functions.

    I am totally messed with all of these.

    Looking forward for your reply, and sincerely happy new year again.

  7. Jason says:

    Would you please send me an email when you reply because I hope I could get your reply in time, thank you soooooo much.

    :)

    • halherta says:

      Jason, I just compiled the example on a Kubuntu 12.04 machine with no problems. Are you using the raspberry pi specific toolchain from “https://github.com/raspberrypi/tools” ?

  8. maurice van hall says:

    If you copy / paste the makefile code, make sure you use a hard tap in the row following “all:” and “clean:”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>