Documentation/Maemo 5 Developer Guide/Development Environment/Maemo SDK

(small typo)
(Maemo Software Development Kit: kinks -> links)
 
(28 intermediate revisions not shown)
Line 1: Line 1:
-
= Maemo SDK =
 
-
 
The following code examples are used in this chapter:
The following code examples are used in this chapter:
-
* [https://garage.maemo.org/svn/maemoexamples/trunk/support-libraries/helloworld.c helloworld.c]
+
* [https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/support-libraries/helloworld.c helloworld.c]
-
* [https://garage.maemo.org/svn/maemoexamples/trunk/support-libraries/gtk_helloworld-1.c gtk_helloworld-1.c]
+
* [https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/support-libraries/gtk_helloworld-1.c gtk_helloworld-1.c]
-
The development environment for Maemo running on the desktop is called '''Maemo SDK'''. You can only install Maemo SDK on a Linux operating system. Maemo SDK currently supports the following Linux distributions:
+
The development environment for Maemo running on the desktop is called the '''Maemo SDK'''. You can only install the Maemo SDK on a Linux operating system. The Maemo SDK currently supports the following Linux distributions:
-
*Debian
+
-
*Ubuntu
+
-
However, you can also install Maemo SDK on other Linux distributions.
+
* Debian
 +
* Ubuntu
-
Maemo Software Development Kit =
+
However, you can also install the Maemo SDK on other Linux distributions.
-
The Maemo SDK creates a sandboxed Maemo development environment on a GNU/Linux desktop system largely built on a tool called [http://scratchbox.org/ Scratchbox]. In most ways, this environment behaves like the operating system on the device, but with added development tools. This means that the development process is very similar to a normal desktop GNU/Linux, and the kinks of embedded development, such as cross-compiling, are handled transparently by Scratchbox.
+
== Maemo Software Development Kit ==
 +
The Maemo SDK creates a sandboxed Maemo development environment on a GNU/Linux desktop system largely built on a tool called [http://scratchbox.org/ Scratchbox]. In most ways, this environment behaves like the operating system on the device, but with added development tools. This means that the development process is very similar to a normal desktop GNU/Linux, and the links of embedded development, such as cross-compiling, are handled transparently by Scratchbox.
-
==Hardware architectures==
+
=== Hardware architectures ===
-
Maemo SDK supports two architectures, ''X86'' and ''ARMEL'' and provides development environment for both. In Fremantle, ''X86'' environment is used for active devleopment and has better tool support through native execution without the need for emulation. ''' ''ARMEL'' ''target'' is used only for cross-compilation of applications to work on the actual device'''. There are currently issues with the user mode qemu which prevent the UI framework from starting up in the ''ARMEL'' target which prevents running applications on this target.
+
The Maemo SDK supports two architectures, <code>X86</code> and <code>ARMEL</code>, and provides development environment for both. In Fremantle, the <code>X86</code> environment is used for active development and has better tool support through native execution without the need for emulation. The <code>ARMEL</code> target is used only for cross-compilation of applications to work on the actual device. There are currently issues with the user mode qemu which prevent the UI framework from starting up in the <code>ARMEL</code> target, which prevents running applications on this target.
-
Once your application compiles, runs and behaves as expected on the ''X86'' ''target'', the next step is to compile it on the ''ARMEL'' ''target''. The process of compilation and packaging is exactly the same as in ''X86'', albeit a bit slower, because some of the required software is emulated. Scratchbox will handle cross-compilation, so the developers need not concern themselves with cross-compilation.
+
When your application compiles, runs and behaves as expected on the <code>X86</code> target, the next step is to compile it on the <code>ARMEL</code> target. The process of compilation and packaging is exactly the same as in <code>X86</code>, albeit a bit slower, because some of the required software is emulated. Scratchbox will handle cross-compilation, so the developers need not concern themselves with cross-compilation.
-
The applications thus compiled on the ''ARMEL'' target can be run directly on the device without further modifications. This is possible because of the emulation provided by the Maemo SDK. The emulation however is not complete, so the actual testing must be performed on the device. <br />
+
The applications thus compiled on the <code>ARMEL</code> target can be run directly on the device without further modifications. This is possible because of the emulation provided by the Maemo SDK. The emulation however is not complete, so the actual testing must be performed on the device.
 +
 
 +
===Scratchbox===
-
==Scratchbox==
 
Scratchbox is a specially packaged "sandbox" environment, providing the necessary tools and isolating the development efforts from the actual Linux system. Scratchbox also makes cross-compiling easy to perform: the software is built into a binary format that is executable on the target device.
Scratchbox is a specially packaged "sandbox" environment, providing the necessary tools and isolating the development efforts from the actual Linux system. Scratchbox also makes cross-compiling easy to perform: the software is built into a binary format that is executable on the target device.
Line 46: Line 45:
This material discusses only the Scratchbox capabilities that are necessary to use the Maemo SDK.  
This material discusses only the Scratchbox capabilities that are necessary to use the Maemo SDK.  
-
 
===Scratchbox In-Depth===
===Scratchbox In-Depth===
-
Scratchbox is Maemo SDK's cross-compiling environment. The default Scratchbox installation works as-is under most conditions, but some details are good to know for more specialized usage.
+
Scratchbox is the Maemo SDK's cross-compiling environment. The default Scratchbox installation works as-is under most conditions, but some details are good to know for more specialized usage.
-
The ''target'' inside Scratchbox contains a root file system. When you create a new target inside Scratchbox, specify the ''toolchain'' you will use to build applications. Examples of a ''target'' include X86 and ARMEL, provided by Maemo SDK on top of Scratchbox.
+
The ''target'' inside Scratchbox contains a root file system. When you create a new target inside Scratchbox, specify the ''toolchain'' you will use to build applications. Examples of a ''target'' include X86 and ARMEL, provided by the Maemo SDK on top of Scratchbox.
''Host tools'' are native to the host, provided for convenience and speed. They are always transparently preferred over target tools. For example, cross-compiling applications to the target architecture. Host tools consist of devkits and ''toolchains''.
''Host tools'' are native to the host, provided for convenience and speed. They are always transparently preferred over target tools. For example, cross-compiling applications to the target architecture. Host tools consist of devkits and ''toolchains''.
-
A toolchain provides the minimal set of tools for compiling binaries for the target. Each scratchbox target must have one and only one toolchain selected.
+
A toolchain provides the minimal set of tools for compiling binaries for the target. Each Scratchbox target must have one and only one toolchain selected.
''CPU transparency methods'' take care of running the applications on an emulator, target device or directly on the host transparently from the user's perspective. The available CPU transparency methods come from a special ''devkit'' called ''cputransp''. For each of Maemo SDK's pre-defined targets, a CPU transparency method is selected and defined.
''CPU transparency methods'' take care of running the applications on an emulator, target device or directly on the host transparently from the user's perspective. The available CPU transparency methods come from a special ''devkit'' called ''cputransp''. For each of Maemo SDK's pre-defined targets, a CPU transparency method is selected and defined.
Line 64: Line 62:
A ''devkit'' is a collection of tools native to the host. A devkit can be selected or disabled for a target. An example of a devkit is the doctools devkit, which provides tools (like doxygen) for building documentation.
A ''devkit'' is a collection of tools native to the host. A devkit can be selected or disabled for a target. An example of a devkit is the doctools devkit, which provides tools (like doxygen) for building documentation.
-
A ''rootstrap'' is a root file system for the target device. Maemo SDK provides root file systems for both targets (X86 and ARMEL) inside Scratchbox. Note that the user's home directory is shared for all targets. The ''/tmp'' directory is shared for all targets and also with the host.
+
A ''rootstrap'' is a root file system for the target device. The Maemo SDK provides root file systems for both targets (X86 and ARMEL) inside Scratchbox. Note that the user's home directory is shared for all targets. The <code>/tmp</code> directory is shared for all targets and also with the host.
-
From Scratchbox's point of view, Maemo SDK is a set of preconfigured ''targets'' and ''root file system''s. One set is provided for both ''X86'' and ''ARMEL'' architectures on top of a working Scratchbox installation.
+
From Scratchbox's point of view, the Maemo SDK is a set of preconfigured ''targets'' and ''root file system''s. One set is provided for both <code>X86</code> and <code>ARMEL</code> architectures on top of a working Scratchbox installation.
 +
==Development in the Maemo SDK==
-
==Development on Maemo SDK==
+
The Maemo SDK provides all of its development tools inside Scratchbox. Also the UI framework is started with a single command, <code>af-sb-init</code>, run within Scratchbox. However, it needs a secondary X server of proper size and bit-depth to be displayed on.
-
The Maemo SDK provides all of its development tools inside Scratchbox. Also the UI framework is started with a single command, ''af-sb-init'', run within Scratchbox. However, it needs a secondary X server of proper size and bit-depth to be displayed on.
+
As an exception to the rule, you must start the Xserver, such as [http://www.freedesktop.org/wiki/Software/Xephyr Xephyr] on the host Linux environment, not inside Scratchbox.
As an exception to the rule, you must start the Xserver, such as [http://www.freedesktop.org/wiki/Software/Xephyr Xephyr] on the host Linux environment, not inside Scratchbox.
 +
=== Scratchbox Development Tools ===
-
===Scratchbox Development Tools===
 
As the Scratchbox environment is practically a full GNU/Linux system, it includes the standard GNU/Linux development tools. Debugging is performed with tools like ''[http://sourceware.org/gdb/ gdb]'', ''[http://valgrind.org/ valgrind]'',  ''ltrace'' and ''[http://sourceforge.net/projects/strace/ strace]''. Performance profiling can be performed with tools like ''[http://htop.sourceforge.net/ htop]'', ''[http://oprofile.sourceforge.net/ oprofile]'' and ''time''. Compiling is done with the GCC toolchain. Some of these tools offer graphical user interfaces, which can also be used. Naturally, this is not a comprehensive list of the tools, and if the tools shipped with the SDK do not suit your needs or personal preferences, most utilities can be easily run practically unchanged in Scratchbox.
As the Scratchbox environment is practically a full GNU/Linux system, it includes the standard GNU/Linux development tools. Debugging is performed with tools like ''[http://sourceware.org/gdb/ gdb]'', ''[http://valgrind.org/ valgrind]'',  ''ltrace'' and ''[http://sourceforge.net/projects/strace/ strace]''. Performance profiling can be performed with tools like ''[http://htop.sourceforge.net/ htop]'', ''[http://oprofile.sourceforge.net/ oprofile]'' and ''time''. Compiling is done with the GCC toolchain. Some of these tools offer graphical user interfaces, which can also be used. Naturally, this is not a comprehensive list of the tools, and if the tools shipped with the SDK do not suit your needs or personal preferences, most utilities can be easily run practically unchanged in Scratchbox.
 +
=== Other Programming Languages ===
-
===Other Programming Languages===
+
Currently C is the only official programming language for Maemo. But thanks to the community, the Python scripting language also has good support in the form of [http://pymaemo.garage.maemo.org/ pymaemo]. [[Scratchbox C++|C++ support for Scratchbox]] is also available.
-
Currently C is the only official programming language for Maemo. But thanks to the community, Python scripting language also has a good support in the form of [http://pymaemo.garage.maemo.org/ pymaemo].
+
-
= Installing SDK =
+
== Installing the SDK ==
-
Before continuing, review the [http://maemo.org/development/sdks/maemo_5_beta_2_sdk_installation/ installation instructions] of the Maemo SDK.
+
Before continuing, review the [[Documentation/Maemo 5 Final SDK Installation|installation instructions]] of the Maemo SDK.
-
The kernel must support binfmt_misc-feature in order for the instruction emulator in Scratchbox to work properly. Because it is usually built as a module, verify that the module is loaded in Linux (no root access needed):
+
The kernel must support the <code>binfmt_misc</code> feature in order for the instruction emulator in Scratchbox to work properly. Because it is usually built as a module, verify that the module is loaded in Linux (no root access needed):
  user@system:~$ lsmod | grep binfmt
  user@system:~$ lsmod | grep binfmt
  binfmt_misc 12936 0
  binfmt_misc 12936 0
-
If you do not see a line of output, try to execute ''modprobe binfmt_misc'' as root (or with sudo). If this still does not work, either locate the module elsewhere, or recompile the kernel. Most Debian-based systems (Debian, Ubuntu) include the module, unless you have built your own kernel, you should encounter no problems. The feature may also be directly built inside the kernel instead of being a module.
+
If you do not see a line of output, try to execute
 +
modprobe binfmt_misc
 +
as root (or with <code>sudo</code>). If this still does not work, either locate the module elsewhere, or recompile the kernel. Most Debian-based systems (Debian, Ubuntu) include the module, unless you have built your own kernel, you should encounter no problems. The feature may also be directly built inside the kernel instead of being a module.
Install a pseudo X server to act as an X client to the real system in order to run application developed after installing the SDK. You have a certain amount of freedom to choose the most suitable option to achieve this, but this material assumes that you are using Xephyr, a Kdrive-based X server/client that can emulate 16-color depth for its clients even while acting as a client to an 24-bit depth real X server. Xephyr also implements modern X protocol extensions.
Install a pseudo X server to act as an X client to the real system in order to run application developed after installing the SDK. You have a certain amount of freedom to choose the most suitable option to achieve this, but this material assumes that you are using Xephyr, a Kdrive-based X server/client that can emulate 16-color depth for its clients even while acting as a client to an 24-bit depth real X server. Xephyr also implements modern X protocol extensions.
Line 99: Line 99:
To install Xephyr on a Debian-based Linux:
To install Xephyr on a Debian-based Linux:
-
* Issue the command sudo apt-get install xserver-xephyr on your real Linux system.
+
* Issue the command <pre>sudo apt-get install xserver-xephyr</pre> on your real Linux system.
-
* Verify installation status by issuing the command 'dpkg -l | grep xephyr' (as non-root).
+
* Verify installation status by issuing the command <pre>dpkg -l | grep xephyr</pre> (as non-root).
-
As mentioned before, Maemo SDK uses Scratchbox as the cross-compilation environment. Therefore, you must install Scratchbox first before attempting to install the SDK. The preferred way to install scratchbox and SDK is to use the automated installation scripts though manual installation steps are also provided. Detailed instructions are found [http://maemo.org/development/sdks/maemo_5_beta_2_sdk_installation/ here].
+
As mentioned before, the Maemo SDK uses Scratchbox as the cross-compilation environment. Therefore, you must install Scratchbox first before attempting to install the SDK. The preferred way to install Scratchbox and the SDK is to use the automated installation scripts, though manual installation steps are also provided. Detailed instructions are found [[Documentation/Maemo 5 Final SDK Installation|on the maemo.org wiki]].
-
= Testing SDK Installation =
+
== Testing SDK Installation ==
 +
 
 +
=== Testing Scratchbox ===
-
== Testing Scratchbox ==
 
The following shows how to create a small non-graphical Hello World program to verify that the Scratchbox environment works: helloworld.c
The following shows how to create a small non-graphical Hello World program to verify that the Scratchbox environment works: helloworld.c
-
<tt><span>''<span><font color="#9A1900">/**</font></span>''</span>
+
<source lang="c">
-
  <span>''<span><font color="#9A1900"> * helloworld.c</font></span>''</span>
+
/**
-
  <span>''<span><font color="#9A1900"> *</font></span>''</span>
+
  * helloworld.c
-
  <span>''<span><font color="#9A1900"> * This maemo code example is licensed under a MIT-style license,</font></span>''</span>
+
  *
-
  <span>''<span><font color="#9A1900"> * that can be found in the file called "License" in the same</font></span>''</span>
+
  * This maemo code example is licensed under a MIT-style license,
-
  <span>''<span><font color="#9A1900"> * directory as this file.</font></span>''</span>
+
  * that can be found in the file called "License" in the same
-
  <span>''<span><font color="#9A1900"> * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.</font></span>''</span>
+
  * directory as this file.
-
  <span>''<span><font color="#9A1900"> *</font></span>''</span>
+
  * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.
-
  <span>''<span><font color="#9A1900"> * Simple standard I/O (printf)-based Hello World that we can use to</font></span>''</span>
+
  *
-
  <span>''<span><font color="#9A1900"> * test our toolchains.</font></span>''</span>
+
  * Simple standard I/O (printf)-based Hello World that we can use to
-
  <span>''<span><font color="#9A1900"> */</font></span>''</span>
+
  * test our toolchains.
-
+
  */
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;stdio.h&gt;</font></span> <span>''<span><font color="#9A1900">/* printf */</font></span>''</span>
+
 
-
+
#include <stdio.h> /* printf */
-
<span>''<span><font color="#9A1900">/* main implementation */</font></span>''</span>
+
 
-
<span><font color="#009900">int</font></span> <span>'''<span><font color="#000000">main</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#009900">int</font></span> argc<span><font color="#990000">,</font></span> <span><font color="#009900">char</font></span><span><font color="#990000"><nowiki>**</nowiki></font></span> argv<span><font color="#990000">)</font></span> <span><font color="#FF0000">{</font></span>
+
/* main implementation */
-
+
int main(int argc, char** argv) {
-
  <span>'''<span><font color="#000000">printf</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"Hello world</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">);</font></span>
+
 
-
+
  printf("Hello world\n");
-
  <span>''<span><font color="#9A1900">/* In Linux, each process upon termination must set its exit code.</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    Exit code 0 means success to whoever executed this program. It</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    is routinely used inside scripts to test whether running some</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    program succeeded or not. Other exit codes mean failure. Each</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    program is free to use different non-zero codes to signify</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    different kinds of failures. These are normally listed in the</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    manual page for the program (since there is no standard). If you</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">    forget to set your exit code, it will be undefined. */</font></span>''</span>
+
-
  <span>'''<span><font color="#0000FF">return</font></span>'''</span> <span><font color="#993399">0</font></span><span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
<span><font color="#FF0000">}</font></span></tt>
+
-
First, we have to verify that the proper directory is chosen. This can be done by using pwd (print working directory). At this point, the work directory should be your home directory:  
+
  /* In Linux, each process upon termination must set its exit code.
 +
    Exit code 0 means success to whoever executed this program. It
 +
    is routinely used inside scripts to test whether running some
 +
    program succeeded or not. Other exit codes mean failure. Each
 +
    program is free to use different non-zero codes to signify
 +
    different kinds of failures. These are normally listed in the
 +
    manual page for the program (since there is no standard). If you
 +
    forget to set your exit code, it will be undefined. */
 +
  return 0;
 +
}
 +
</source>
 +
 
 +
First, verify that the proper directory is chosen by using <code>pwd</code> (print working directory). At this point, the work directory should be your home directory:  
  [sbox-FREMANTLE_X86: ~] &gt; pwd
  [sbox-FREMANTLE_X86: ~] &gt; pwd
  /home/user
  /home/user
-
 
Then, start an editor and write a small hello world program (you may use the above code listing as a template if you wish):  
Then, start an editor and write a small hello world program (you may use the above code listing as a template if you wish):  
Line 149: Line 151:
  [sbox-FREMANTLE_X86: ~] &gt; nano helloworld.c
  [sbox-FREMANTLE_X86: ~] &gt; nano helloworld.c
-
It is also possible to use vi (Visual Interactive) editor inside Scratchbox. It is possible to install your own favourite editor inside sbox (with the debian-devkit), but the following examples will use nano, since it is the easiest to start with. If you want to learn vi, your best course of action is searching for "vi tutorial" with your favourite search engine. There are lots of them to be found. To understand why vi can be considered "strange", it is useful to know its history first. Using vi is fully optional, of course.
+
It is also possible to use the <code>vi</code> (Visual Interactive) editor inside Scratchbox. You can install your own favourite editor inside Scratchbox (with the debian-devkit), but the following examples will use <code>nano</code>, because it is the easiest to start with. If you want to learn <code>vi</code>, your best course of action is searching for "vi tutorial" with your favourite search engine. There are lots of them to be found. To understand why <code>vi</code> can be considered "strange", it is useful to know its history first. Using vi is fully optional.
   
   
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g helloworld.c -o helloworld
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g helloworld.c -o helloworld
Line 155: Line 157:
  helloworld* helloworld.c
  helloworld* helloworld.c
-
GCC's -g option tells the compiler to add debugging symbols to the generated output file. -Wall will tell the compiler to enable most of the syntax and other warnings that the source code could trigger. -o helloworld tells gcc to output the resulting binary with the filename of helloworld.
+
GCC's <code>-g</code> option tells the compiler to add debugging symbols to the generated output file. <code>-Wall</code> will tell the compiler to enable most of the syntax and other warnings that the source code could trigger. <code>-o helloworld</code> tells gcc to output the resulting binary with the filename of helloworld.
-
The -F option to ls is mainly useful when working with a non-color terminal (e.g. paper) to indicate the type of different files. The asterisk after helloworld signifies that the file is an executable. <br />
+
The <code>-F</code> option to <code>ls</code> is mainly useful when working with a non-color terminal (for example paper) to indicate the type of different files. The asterisk after helloworld signifies that the file is executable.
  [sbox-FREMANTLE_X86: ~] &gt; ./helloworld
  [sbox-FREMANTLE_X86: ~] &gt; ./helloworld
Line 163: Line 165:
Running the binary should not produce any surprises.  
Running the binary should not produce any surprises.  
-
 
  [sbox-FREMANTLE_X86: ~] &gt; file helloworld
  [sbox-FREMANTLE_X86: ~] &gt; file helloworld
Line 169: Line 170:
  for GNU/Linux 2.6.0, dynamically linked (uses shared libs), not stripped
  for GNU/Linux 2.6.0, dynamically linked (uses shared libs), not stripped
-
The file tool is a generic utility that will load some bytes from the start of the given file and then use its internal database to decode what type of file it is. In this case, it will correctly decode the file as a X86 format binary file.  
+
The file tool is a generic utility that loads some bytes from the start of the given file and then uses its internal database to decode what type of file it is. In this case, it will correctly decode the file as a X86 format binary file.  
   
   
  [sbox-FREMANTLE_X86: ~] &gt; ldd helloworld
  [sbox-FREMANTLE_X86: ~] &gt; ldd helloworld
Line 180: Line 181:
  -rwxr-xr-x  1 user user 1213256 Sep  7 13:28 /lib/libc-2.5.so
  -rwxr-xr-x  1 user user 1213256 Sep  7 13:28 /lib/libc-2.5.so
 +
On the left are the names of dynamic libraries that the executable uses, and on the right are the files where the libraries reside on the system when executing the program. Next use <code>ls</code> to check the exact version of the C library that the SDK uses with the "long listing format" <code>-l</code> option. Running these commands using the<code> ARMEL</code> target yields more or less the same results.
 +
N.B. The <code>linux-gate.so.1</code> library is a so-called hack to support a certain way of doing system calls on the X86 architecture, and is not always present on newer systems.
-
On the left are the names of dynamic libraries that the executable uses, and on the right are the files where the libraries reside on the system when executing the program. Next use ls to check the exact version of the C library that the SDK uses with the "long listing format" -l option. Running these commands using the ARMEL target would yield more or less the same results. Note: The linux-gate.so.1 is a so-called hack to support a certain way of doing system calls on the X86 architecture, and is not always present on newer systems.
+
When comparing the version of libc used on the real system with <code>ls -l</code>, it will probably show a difference (in version numbers). This means that the executables that were built inside Scratchbox use libraries that are also inside Scratchbox. This also means we have a stable development platform, which is very important, especially when working on a team where each member has their own Linux installation which they may or may not have customized. This might not seem very important at this stage, but when encountering all the different tools that are used in free software development, this feature of Scratchbox will come in handy.
-
When comparing the version of libc used on the real system with ls -l, it will probably show a difference (in version numbers). This means that the executables that were built inside sbox use libraries that are also inside sbox. This also means we have a stable development platform, which is very important, especially when working on a team where each member has their own Linux installation which they may or may not have customized. This might not seem very important at this stage, but when encountering all the different tools that are used in free software development, this feature of sbox will come in handy.
+
Scratchbox does not contain any logic to emulate the kernel (or to use a different kernel for running programs inside Scratchbox). The only easy possibility for this is using the sbrsh CPU-transparency option.  
-
Scratchbox does not contain any logic to emulate the kernel (or to use a different kernel for running programs inside sbox). The only easy possibility for this is using the sbrsh CPU-transparency option.
+
==== vi ====
-
===vi===
+
You can also use the <code>vi</code> (Visual Interactive) editor inside Scratchbox. You can install your own favorite editor inside Scratchbox (with the debian-devkit), but the following examples will use <code>nano</code>, since it is the easiest to start with. If you want to learn <code>vi</code>, search for "vi tutorial" with your favorite search engine. There are lots of them to be found. To understand why <code>vi</code> can be considered "strange", it is useful to know its history first. Using <code>vi</code> is fully optional. It is common for people who are new to <code>vi</code> to get stuck in it; if you find yourself in this situation, a way to exit (without writing the file) is to press type <escape>:qall!<enter>.
-
It is also possible to use vi (Visual Interactive) editor inside sbox. It is possible to install your own favorite editor inside sbox (with the debian-devkit), but the following examples will use nano, since it is the easiest to start with. If you want to learn vi, your best course of action is searching for "vi tutorial" with your favorite search engine. There are lots of them to be found. To understand why vi can be considered "strange", it is useful to know its history first. Using vi is fully optional, of course.
+
-
The vi that is commonly installed on Linux systems is really vim (VI iMproved), which is a more user-friendly version of vi, including syntax high-lighting and all kinds of improvements. sbox has a program called vimtutor installed to help you learn how to use vi interactively.
+
The <code>vi</code> that is commonly installed on Linux systems is really <code>vim</code> (VI iMproved), which is a more user-friendly version of <code>vi</code>, including syntax hilighting and all kinds of improvements. Scratchbox has a program called <code>vimtutor</code> installed to help you learn how to use <code>vi</code> interactively.
-
It is also fairly simple to use existing editors. /scratchbox/users/x/home/x/ is the home directory of user x when accessing it from the real Linux desktop. Ubuntu comes with gedit, which is a fairly good graphical editor that also supports syntax highlighting and multiple tabs for editing multiple files at the same time.
+
It is also fairly simple to use existing editors. <code>/scratchbox/users/x/home/x/</code> is the home directory of user x when accessing it from the real Linux desktop. Ubuntu comes with Gedit, which is a fairly good graphical editor that also supports syntax highlighting and multiple tabs for editing multiple files at the same time.
-
And as a final note, emacs can also be used.
+
And as a final note, <code>emacs</code> can also be used.
Here is how to do use it:
Here is how to do use it:
Line 202: Line 204:
* Inside Scratchbox, use the emacsclient filename to open the file for editing in your emacs
* Inside Scratchbox, use the emacsclient filename to open the file for editing in your emacs
-
==Writing GUI Hello World==
+
=== Writing GUI Hello World ===
-
The following example shows how to write the first GUI program. Note that the example only uses the GTK+ library and does not utilise the widgets and coding style provided by the platform. That will be discussed soon.  
+
 
 +
The following example shows how to write the first GUI program. Note that the example only uses the GTK+ library and does not utilise the widgets and coding style provided by the platform. That will be discussed later.  
gtk_helloworld-1.c
gtk_helloworld-1.c
-
<tt><span>''<span><font color="#9A1900">/**</font></span>''</span>
+
<source lang="c">
-
  <span>''<span><font color="#9A1900"> * gtk_helloworld-1.c</font></span>''</span>
+
/**
-
  <span>''<span><font color="#9A1900"> *</font></span>''</span>
+
  * gtk_helloworld-1.c
-
  <span>''<span><font color="#9A1900"> * This maemo code example is licensed under a MIT-style license,</font></span>''</span>
+
  *
-
  <span>''<span><font color="#9A1900"> * that can be found in the file called "License" in the same</font></span>''</span>
+
  * This maemo code example is licensed under a MIT-style license,
-
  <span>''<span><font color="#9A1900"> * directory as this file.</font></span>''</span>
+
  * that can be found in the file called "License" in the same
-
  <span>''<span><font color="#9A1900"> * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.</font></span>''</span>
+
  * directory as this file.
-
  <span>''<span><font color="#9A1900"> *</font></span>''</span>
+
  * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.
-
  <span>''<span><font color="#9A1900"> * A simple GTK+ Hello World. You need to use Ctrl+C to terminate</font></span>''</span>
+
  *
-
  <span>''<span><font color="#9A1900"> * this program since it doesn't implement GTK+ signals (yet).</font></span>''</span>
+
  * A simple GTK+ Hello World. You need to use Ctrl+C to terminate
-
  <span>''<span><font color="#9A1900"> */</font></span>''</span>
+
  * this program since it doesn't implement GTK+ signals (yet).
-
+
  */
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;stdlib.h&gt;</font></span> <span>''<span><font color="#9A1900">/* EXIT_* */</font></span>''</span>
+
 
-
<span>''<span><font color="#9A1900">/* Introduce types and prototypes of GTK+ for the compiler. */</font></span>''</span>
+
#include <stdlib.h> /* EXIT_* */
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;gtk/gtk.h&gt;</font></span>
+
/* Introduce types and prototypes of GTK+ for the compiler. */
-
+
#include <gtk/gtk.h>
-
<span><font color="#009900">int</font></span> <span>'''<span><font color="#000000">main</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#009900">int</font></span> argc<span><font color="#990000">,</font></span> <span><font color="#009900">char</font></span><span><font color="#990000"><nowiki>**</nowiki></font></span> argv<span><font color="#990000">)</font></span> <span><font color="#FF0000">{</font></span>
+
 
-
+
int main(int argc, char** argv) {
-
  <span>''<span><font color="#9A1900">/* We'll have two references to two GTK+ widgets. */</font></span>''</span>
+
 
-
  GtkWindow<span><font color="#990000"><nowiki>*</nowiki></font></span> window<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
  /* We'll have two references to two GTK+ widgets. */
-
  GtkLabel<span><font color="#990000"><nowiki>*</nowiki></font></span> label<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
  GtkWindow* window;
-
+
  GtkLabel* label;
-
  <span>''<span><font color="#9A1900">/* Initialize the GTK+ library. */</font></span>''</span>
+
 
-
  <span>'''<span><font color="#000000">gtk_init</font></span>'''</span><span><font color="#990000">(&amp;</font></span>argc<span><font color="#990000">,</font></span> <span><font color="#990000">&amp;</font></span>argv<span><font color="#990000">);</font></span>
+
  /* Initialize the GTK+ library. */
-
+
  gtk_init(&argc, &argv);
-
  <span>''<span><font color="#9A1900">/* Create a window with window border width of 12 pixels and a</font></span>''</span>
+
 
-
<span>''<span><font color="#9A1900">    title text. */</font></span>''</span>
+
  /* Create a window with window border width of 12 pixels and a
-
  window <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">g_object_new</font></span>'''</span><span><font color="#990000">(</font></span>GTK_TYPE_WINDOW<span><font color="#990000">,</font></span>
+
    title text. */
-
    <span><font color="#FF0000">"border-width"</font></span><span><font color="#990000">,</font></span> <span><font color="#993399">12</font></span><span><font color="#990000">,</font></span>
+
  window = g_object_new(GTK_TYPE_WINDOW,
-
    <span><font color="#FF0000">"title"</font></span><span><font color="#990000">,</font></span> <span><font color="#FF0000">"Hello GTK+"</font></span><span><font color="#990000">,</font></span>
+
    "border-width", 12,
-
    NULL<span><font color="#990000">);</font></span>
+
    "title", "Hello GTK+",
-
+
    NULL);
-
  <span>''<span><font color="#9A1900">/* Create the label widget. */</font></span>''</span>
+
 
-
  label <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">g_object_new</font></span>'''</span><span><font color="#990000">(</font></span>GTK_TYPE_LABEL<span><font color="#990000">,</font></span>
+
  /* Create the label widget. */
-
    <span><font color="#FF0000">"label"</font></span><span><font color="#990000">,</font></span> <span><font color="#FF0000">"Hello World!"</font></span><span><font color="#990000">,</font></span>
+
  label = g_object_new(GTK_TYPE_LABEL,
-
    NULL<span><font color="#990000">);</font></span>
+
    "label", "Hello World!",
-
+
    NULL);
-
  <span>''<span><font color="#9A1900">/* Pack the label into the window layout. */</font></span>''</span>
+
 
-
  <span>'''<span><font color="#000000">gtk_container_add</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_CONTAINER</font></span>'''</span><span><font color="#990000">(</font></span>window<span><font color="#990000">),</font></span> <span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>label<span><font color="#990000">));</font></span>
+
  /* Pack the label into the window layout. */
-
+
  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(label));
-
  <span>''<span><font color="#9A1900">/* Show all widgets that are contained by the window. */</font></span>''</span>
+
 
-
  <span>'''<span><font color="#000000">gtk_widget_show_all</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>window<span><font color="#990000">));</font></span>
+
  /* Show all widgets that are contained by the window. */
-
+
  gtk_widget_show_all(GTK_WIDGET(window));
-
  <span>''<span><font color="#9A1900">/* Start the main event loop. */</font></span>''</span>
+
 
-
  <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"main: calling gtk_main</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">);</font></span>
+
  /* Start the main event loop. */
-
  <span>'''<span><font color="#000000">gtk_main</font></span>'''</span><span><font color="#990000">();</font></span>
+
  g_print("main: calling gtk_main\n");
-
+
  gtk_main();
-
  <span>''<span><font color="#9A1900">/* Display a message to the standard output and exit. */</font></span>''</span>
+
 
-
  <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"main: returned from gtk_main and exiting with success</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">);</font></span>
+
  /* Display a message to the standard output and exit. */
-
+
  g_print("main: returned from gtk_main and exiting with success\n");
-
  <span>''<span><font color="#9A1900">/* The C standard defines this condition as EXIT_SUCCESS, and this</font></span>''</span>
+
 
-
<span>''<span><font color="#9A1900">    symbolic macro is defined in stdlib.h (which GTK+ will pull in</font></span>''</span>
+
  /* The C standard defines this condition as EXIT_SUCCESS, and this
-
<span>''<span><font color="#9A1900">    in-directly). There is also a counter-part for failures:</font></span>''</span>
+
    symbolic macro is defined in stdlib.h (which GTK+ will pull in
-
<span>''<span><font color="#9A1900">    EXIT_FAILURE. */</font></span>''</span>
+
    in-directly). There is also a counter-part for failures:
-
  <span>'''<span><font color="#0000FF">return</font></span>'''</span> EXIT_SUCCESS<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
    EXIT_FAILURE. */
-
<span><font color="#FF0000">}</font></span></tt>
+
  return EXIT_SUCCESS;
 +
}
 +
</source>
Build your program:
Build your program:
Line 287: Line 292:
-
This does not look at all promising. The source code started with #include, and you need to tell the compiler where to look for that critical GTK+ header file. The compiler probably also needs some special flags to be able to use the correct compilation settings for building GTK+ software.
+
This does not look at all promising. The source code started with <code>#include</code>, and you need to tell the compiler where to look for that critical GTK+ header file. The compiler probably also needs some special flags to be able to use the correct compilation settings for building GTK+ software.
-
To help you decide which flags to use we provide a tool called pkg-config, which is a simple program that provides a unified interface to output compiler, linker flags and library version numbers. Use pkg-config manually for the time being.  
+
To help you decide which flags to use we provide a tool called <code>pkg-config</code>, which is a simple program that provides a unified interface to output compiler, linker flags and library version numbers. Use <code>pkg-config</code> manually for the time being.
   
   
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --list-all | sort
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --list-all | sort
Line 305: Line 310:
  x11            X11 - X Library
  x11            X11 - X Library
-
 
+
<code>pkg-config</code> also has some other useful commands:
-
pkg-config also has some other useful commands:
+
   
   
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --modversion gtk+-2.0
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --modversion gtk+-2.0
Line 318: Line 322:
  -I/usr/include/libpng12
  -I/usr/include/libpng12
-
 
+
In this version of GTK+, all these commands are <code>-I</code> options that tell the compiler which additional directories to check for system header files in addition to the default ones.  
-
In this version of GTK+, all these commands are -I options that tell the compiler which additional directories to check for system header files in addition to the default ones.  
+
   
   
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --libs gtk+-2.0
  [sbox-FREMANTLE_X86: ~] &gt; pkg-config --libs gtk+-2.0
Line 325: Line 328:
  -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2
  -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2
  -ldl -lglib-2.0
  -ldl -lglib-2.0
-
 
When linking the application, the linker has to be told which libraries to link against. In fact, the whole program linking phase will fail (as shown below) without this information.
When linking the application, the linker has to be told which libraries to link against. In fact, the whole program linking phase will fail (as shown below) without this information.
-
Now compile the software again, and this time use the compilation flags that pkg-config provides:  
+
Now compile the software again, and this time use the compilation flags that <code>pkg-config</code> provides:  
-
 
-
<nowiki>
 
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g gtk_helloworld-1.c  \
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g gtk_helloworld-1.c  \
   `pkg-config --cflags gtk+-2.0` -o gtk_helloworld-1
   `pkg-config --cflags gtk+-2.0` -o gtk_helloworld-1
Line 353: Line 353:
  :/home/user/gtk_helloworld-1.c:49: undefined reference to `g_print'
  :/home/user/gtk_helloworld-1.c:49: undefined reference to `g_print'
  collect2: ld returned 1 exit status
  collect2: ld returned 1 exit status
-
</nowiki>
 
 +
The command above may be new to you, if you have not used UNIX command shells.  This is a backtick expansion, an operation where the shell starts another shell only to execute the text inside the backticks. In this case, start another shell to run <code>`pkg-config --cflags gtk+-2.0`</code>. Normal output from the commands is then read into the main shell and the output is replaced into the location where the backticks were.
 +
N.B. Use the backtick character (`) or falling accent. Do not use a rising accent (´) or a single quote or apostrophe ('). In some keyboard layouts, you can get the backtick character to appear by pressing first the backtic and then the space bar.
-
The command above may be new to you, if you have not used UNIX command shells.  This is a backtick expansion, an operation where the shell starts another shell only to execute the text inside the backticks. In this case, you start another shell to run ''`pkg-config --cflags gtk+-2.0`''. Normal output from the commands is then read into the main shell and the output is replaced into the location where the backticks were. Note: It is very important to use the backtick character (`) or falling accent. Do not use a rising accent (´) or a single quote or apostrophe ('). In some keyboard layouts, you can get the backtick character to appear by pressing first the backtic and then the space bar.
+
An alternative operation is <code>$(pkg-config ..)</code>, which corresponds to the backtick but is less portable across antique UNIX shells. Choosing between these is a matter of taste.
-
An alternative operation is $(pkg-config ..), which corresponds to the backtick but is less portable across antique UNIX shells. Choosing between these is a matter of taste.
+
GCC prints very different errors this time. These errors come from <code>ld</code>, which is the binary code linker in Linux systems and complains about missing symbols (the undefined references). Obviously something is still missing.
-
GCC prints very different errors this time. These errors come from ld, which is the binary code linker in Linux systems and complains about missing symbols (the undefined references). Obviously something is still missing.
+
You must tell the linker where to find the missing symbols. Because this is the linker and not the compiler that we are talking about, the missing symbols are in the library files.
-
You must tell the linker where to find the missing symbols. Because this is the linker and not the compiler that we are talking aobut, the missing symbols are in the library files.
+
To fix the problem (again using backticks), <code>pkg-config --libs</code> can be used:
-
To fix the problem (again using backticks), pkg-config libs can be used:
 
-
 
-
 
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g gtk_helloworld-1.c  \
  [sbox-FREMANTLE_X86: ~] &gt; gcc -Wall -g gtk_helloworld-1.c  \
-
   `pkg-config --cflags gtk+-2.0` -o gtk_helloworld-1 \
+
   `pkg-config --cflags --libs gtk+-2.0` -o gtk_helloworld-1
-
  `pkg-config --libs gtk+-2.0`
+
  [sbox-FREMANTLE_X86: ~] &gt;
  [sbox-FREMANTLE_X86: ~] &gt;
-
 
-
 
-
The order and placement of the pkg-config commands above is important: you must place the cflags as early as feasible and ensure that the libs must come last (this does matter in some problematic linking scenarios).
 
The next step is to repeat the basic commands that you used before with the non-GUI hello world:  
The next step is to repeat the basic commands that you used before with the non-GUI hello world:  
-
 
  [sbox-FREMANTLE_X86: ~] &gt; ls -l gtk_helloworld-1
  [sbox-FREMANTLE_X86: ~] &gt; ls -l gtk_helloworld-1
Line 415: Line 408:
   libXdmcp.so.6 =&gt; /usr/lib/libXdmcp.so.6 (0xb7689000)
   libXdmcp.so.6 =&gt; /usr/lib/libXdmcp.so.6 (0xb7689000)
   libexpat.so.1 =&gt; /usr/lib/libexpat.so.1 (0xb7669000)
   libexpat.so.1 =&gt; /usr/lib/libexpat.so.1 (0xb7669000)
-
 
As you can see from the last ldd listing, this simple Hello World requires several other libraries to run. The program itself only requires GTK+, but GTK+ needs GDK and all the other libraries that were covered in the introduction. Those libraries in turn need other libraries and so on.
As you can see from the last ldd listing, this simple Hello World requires several other libraries to run. The program itself only requires GTK+, but GTK+ needs GDK and all the other libraries that were covered in the introduction. Those libraries in turn need other libraries and so on.
Line 425: Line 417:
You need all of these tools later on when starting the packaging of the software.
You need all of these tools later on when starting the packaging of the software.
-
== Running GUI Hello World ==
+
=== Running GUI Hello World ===
-
Let's try to execute our nice Hello World (inside sbox):  
+
 
 +
Let's try to execute Hello World inside Scratchbox:  
  [sbox-FREMANTLE_X86: ~] &gt; ./gtk_helloworld-1
  [sbox-FREMANTLE_X86: ~] &gt; ./gtk_helloworld-1
Line 432: Line 425:
  [sbox-FREMANTLE_X86: ~] &gt; echo $DISPLAY
  [sbox-FREMANTLE_X86: ~] &gt; echo $DISPLAY
 +
GTK+ seems unable to open connection to the X server. To verify this, display the contents of the DISPLAY environmental variable; indeed, the variable is empty. If the <code>DISPLAY</code> variable contains <code>:0.0</code>, the value originates in the graphical session and was copied into Scratchbox. Clients try to connect to the real X server and probably fail during authentication.
-
GTK+ seems unable to open connection to the X server. To verify this, display the contents of the DISPLAY environmental variable; indeed, the variable is empty. If the DISPLAY variable contains :0.0, the value originates in the graphical session and was copied into Scratchbox. Clients try to connect to the real X server and probably fail during authentication.
+
=== Starting Virtual X Server (Xephyr) ===
-
Start Xephyr (installed in the previous chapter) to use it as the server for all clients running inside the Scratchbox session.
+
Run Xephyr outside the Scratchbox environment:
-
== Starting Virtual X Server (Xephyr) ==
+
$ Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac -kb &
-
Open another terminal emulator (do not close your Scratchbox session).
+
=== Directing Client to Virtual Server ===
-
 
+
-
Start up the server with:
+
-
 
+
-
user@system:~$ Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac
+
-
 
+
-
 
+
-
The first parameter is the Display number (:2) that X server should start on (and provide to clients). :2 is used here, since it is normally unused in regular Linux desktop environments.
+
-
 
+
-
The screen parameters tells Xephyr how large the screen should be (in pixels), and how many bits to use for color-information (16). This is the resolution in pixels of Maemo compatible device. -dpi 96 tells the server to tell its clients that the logical to physical size mapping should be done with 96 dots-per-inch setting (should the client request that information). The DPI setting is mainly important when dealing with fonts and text.
+
-
 
+
-
-ac tells Xephyr that any client may connect to it. Treat the networking environment with extreme caution so that rogue users do not target your Xephyr with their own clients.
+
-
 
+
-
The last parameter (-extension Composite) disables the Composite extension.
+
-
 
+
-
When Xephyr starts, it connects to the X server given in the DISPLAY environmental variable that it sees. Do not modify or touch your real DISPLAY variable that Xephyr sees.
+
-
 
+
-
By default, the server server has one screen that is filled by the default X server background pattern (a tight braid made out of white pixels on black).
+
-
 
+
-
N.B. The terminal emulator (more specifically, the shell that the emulator started) is waiting for Xephyr to end, and closing Xephyr terminates all the graphical applications running in the SDK. This leaves the daemons running inside Scratchbox (D-Bus and friends). Usually this is not a good idea. Use Ctrl+C to terminate the foreground process. The same technique can be used inside Scratchbox to terminate a graphical client started from the command line.
+
-
 
+
-
== Directing Client to Virtual Server ==
+
Now that there is an X server running, switch back to Scratchbox.
Now that there is an X server running, switch back to Scratchbox.
-
The first step is to set the environmental variable so that X server knows to use a local domain socket, and tell all X clients to connect to Display number 2, since that is where Xephyr started:  
+
The first step is to set the environmental variable so that the X server knows to use a local domain socket, and tell all X clients to connect to Display number 2, since that is where Xephyr started:  
-
<nowiki>
 
  [sbox-FREMANTLE_X86: ~] &gt; export DISPLAY=:2
  [sbox-FREMANTLE_X86: ~] &gt; export DISPLAY=:2
  [sbox-FREMANTLE_X86: ~] &gt; ./gtk_helloworld-1
  [sbox-FREMANTLE_X86: ~] &gt; ./gtk_helloworld-1
  main: calling gtk_main
  main: calling gtk_main
-
  [[Ctrl+c]]
+
  [Ctrl+c]
-
</nowiki>
+
-
 
+
Use Ctrl+C to terminate the program because it does not implement any graphical methods for closing.  
Use Ctrl+C to terminate the program because it does not implement any graphical methods for closing.  
-
''N.B.'' The DISPLAY needs to be set correctly on each Scratchbox login (or when switching targets).
+
''N.B.'' The <code>DISPLAY</code> needs to be set correctly on each Scratchbox login (or when switching targets).
Since you did not start a window manager for the X server, you cannot control Hello World with the mouse. Use Ctrl+C to terminate Hello World; you will start it again in a moment.
Since you did not start a window manager for the X server, you cannot control Hello World with the mouse. Use Ctrl+C to terminate Hello World; you will start it again in a moment.
-
To quickly detach the foreground process from the shell and continue running the process in the background, press Ctrl+Z and then use the shell command bg. The process is "paused" between these two steps.
+
To quickly detach the foreground process from the shell and continue running the process in the background, press Ctrl+Z and then use the shell command <code>bg</code>. The process is "paused" between these two steps.
-
== Starting Application Framework ==
+
=== Starting Application Framework ===
-
The next step is to have a nice graphical environment that will implement a nicer graphical screen. For this, a series of clients will be started, each of which have a specific role. These were introduced before.
+
The next step is to have a graphical environment that will implement a nicer graphical screen. For this, a series of clients will be started, each of which have a specific role. These were introduced before.
-
To start the UI Framework, it is possible to use a handy script that comes with the SDK:  
+
To start the UI Framework, you can use a handy script that comes with the SDK:  
  [sbox-FREMANTLE_X86: ~] &gt; af-sb-init.sh start
  [sbox-FREMANTLE_X86: ~] &gt; af-sb-init.sh start
Line 492: Line 462:
The start and stop parameters are used to start and stop the graphical environment. If everything works, it should show a screen resembling this one:
The start and stop parameters are used to start and stop the graphical environment. If everything works, it should show a screen resembling this one:
 +
[[Image:UI-startup.png|frame|center|alt=Screenshot of SDK user interface|SDK UI]]
-
[[Image:UI-startup.png|400px]]
+
=== Running Hello World in Application Framework ===
-
==Running Hello World in Application Framework ==
 
While the UI framework is running, the Hello World can be started again  
While the UI framework is running, the Hello World can be started again  
[sbox-FREMANTLE_X86: ~] >./gtk_helloworld-1
[sbox-FREMANTLE_X86: ~] >./gtk_helloworld-1
-
[[Image:helloworld-without-theme.png|400px]]
+
[[Image:helloworld-without-theme.png|frame|center|alt=Screenshot of test application showing ‘Hello World!’ in the centre of an unthemed window|Hello world]]
-
Since there now is a window manager running, the client will get much larger window to draw in. GTK+ will scale the widget accordingly (there is only one widget in the program).  
+
Because there now is a window manager running, the client gets much larger window to draw in. GTK+ scales the widget accordingly (there is only one widget in the program).  
-
NOTE: The screen still looks a bit off. If the application is closed by pressing the X in the top-right corner, you can see that the Hello World will disappear from the screen. Since no signals have been implemented yet and thus there is nothing to handle window destruction, the Hello World application will only be hidden. It is still running (as can be seen in the sbox terminal emulator, since the shell does not display its prompt). Stop the Hello World program with Ctrl+C.
+
The screen still looks a bit off. If the application is closed by pressing the X in the top-right corner, you can see that the Hello World disappears from the screen. Because no signals have been implemented yet and thus there is nothing to handle window destruction, the Hello World application is only hidden. It is still running (as can be seen in the sbox terminal emulator, since the shell does not display its prompt). Stop the Hello World program with Ctrl+C.
The next step shows how to use an SDK utility script called run-standalone.sh. Its job is to set up the correct environment variables for themes and communication for the command that is given to it as its command line parameter.
The next step shows how to use an SDK utility script called run-standalone.sh. Its job is to set up the correct environment variables for themes and communication for the command that is given to it as its command line parameter.
Line 510: Line 480:
  [sbox-FREMANTLE_X86: ~] >run-standalone.sh ./gtk_helloworld-1
  [sbox-FREMANTLE_X86: ~] >run-standalone.sh ./gtk_helloworld-1
-
[[Image:helloworld-with-theme.png|400px]]
+
[[Image:helloworld-with-theme.png|frame|center|alt=Screenshot of test application showing ‘Hello World!’ in the centre of a themed window|Themed Hello world]]
 +
 
 +
The screen is still a bit off (there are no borders around the main <code>GtkLabel</code> widget), but already looks better. The text is scaled to be more in sync with the other text sizes and the color is also in sync with the platform color (it is not gray anymore).
-
The screen is still a bit off (there are no borders around the main GtkLabel widget), but already looks better. The text is scaled to be more in sync with the other text sizes and the color is also in sync with the platform color (it is not gray anymore).
+
[[Category:Documentation]]
 +
[[Category:Fremantle]]
 +
[[Category:Scratchbox]]

Latest revision as of 10:38, 7 June 2015

The following code examples are used in this chapter:

The development environment for Maemo running on the desktop is called the Maemo SDK. You can only install the Maemo SDK on a Linux operating system. The Maemo SDK currently supports the following Linux distributions:

  • Debian
  • Ubuntu

However, you can also install the Maemo SDK on other Linux distributions.

Contents

[edit] Maemo Software Development Kit

The Maemo SDK creates a sandboxed Maemo development environment on a GNU/Linux desktop system largely built on a tool called Scratchbox. In most ways, this environment behaves like the operating system on the device, but with added development tools. This means that the development process is very similar to a normal desktop GNU/Linux, and the links of embedded development, such as cross-compiling, are handled transparently by Scratchbox.

[edit] Hardware architectures

The Maemo SDK supports two architectures, X86 and ARMEL, and provides development environment for both. In Fremantle, the X86 environment is used for active development and has better tool support through native execution without the need for emulation. The ARMEL target is used only for cross-compilation of applications to work on the actual device. There are currently issues with the user mode qemu which prevent the UI framework from starting up in the ARMEL target, which prevents running applications on this target.

When your application compiles, runs and behaves as expected on the X86 target, the next step is to compile it on the ARMEL target. The process of compilation and packaging is exactly the same as in X86, albeit a bit slower, because some of the required software is emulated. Scratchbox will handle cross-compilation, so the developers need not concern themselves with cross-compilation.

The applications thus compiled on the ARMEL target can be run directly on the device without further modifications. This is possible because of the emulation provided by the Maemo SDK. The emulation however is not complete, so the actual testing must be performed on the device.

[edit] Scratchbox

Scratchbox is a specially packaged "sandbox" environment, providing the necessary tools and isolating the development efforts from the actual Linux system. Scratchbox also makes cross-compiling easy to perform: the software is built into a binary format that is executable on the target device.

The name "Scratchbox" comes from "Linux from scratch" + "chroot jail" (sandbox). This also explains its implementation and intended use. While working inside Scratchbox, programs will be running in a changed root environment (chroot). In Linux systems, it is possible to change the file paths that a process will see. Scratchbox uses this mechanism on startup to switch its root directory (/) to something other than the real root. This is part of the isolation technique used. Because of this, the environment is called a sandbox, a private area where it is possible to play around without disturbing the environment, and without all the mess that real sand would cause. The other parts of the isolation technique are library call diversions (using LD_PRELOAD), wrapping of compiler executables and other commands.

Scratchbox:

  • Is a software package to implement development sandboxes (for isolation)
  • Contains easy-to-use tools to assist cross-compilation
  • Supports multiple developers using the same development system
  • Supports multiple configurations for each developer
  • Supports executing target executables on the hardware target, via a mechanism called sbrsh
  • Supports running non-native binaries on the host system via instruction set emulators (Qemu is used).

Besides these main features, it is possible to develop your own software packages that can be installed and used inside a Scratchbox environment. Scratchbox also includes some integration of Debian package management, so that once the source files are set up correctly and a couple of configuration files have been written, binary distribution packages can be created for various architectures (similar to .msi files in Windows, or .rpm files in Fedora Core, RHEL and SUSE). These tools are also used to provide the environment with a packaging database so that other development packages can be installed over the Internet when needed (by using standard Debian package management tools).

Fremantle also uses a similar packaging system, and this means that packages built using Scratchbox and the SDK can be installed on the real device.

Scratchbox is licensed under the GPL and it is open for outside contributions. For in-depth coverage on Scratchbox and its capabilities, please visit the project website.

This material discusses only the Scratchbox capabilities that are necessary to use the Maemo SDK.

[edit] Scratchbox In-Depth

Scratchbox is the Maemo SDK's cross-compiling environment. The default Scratchbox installation works as-is under most conditions, but some details are good to know for more specialized usage.

The target inside Scratchbox contains a root file system. When you create a new target inside Scratchbox, specify the toolchain you will use to build applications. Examples of a target include X86 and ARMEL, provided by the Maemo SDK on top of Scratchbox.

Host tools are native to the host, provided for convenience and speed. They are always transparently preferred over target tools. For example, cross-compiling applications to the target architecture. Host tools consist of devkits and toolchains.

A toolchain provides the minimal set of tools for compiling binaries for the target. Each Scratchbox target must have one and only one toolchain selected.

CPU transparency methods take care of running the applications on an emulator, target device or directly on the host transparently from the user's perspective. The available CPU transparency methods come from a special devkit called cputransp. For each of Maemo SDK's pre-defined targets, a CPU transparency method is selected and defined.

A toolchain is a collection of tools used to produce binaries for the target environment. In addition to a compiler (gcc), the toolchain contains a linker (ld) and other binutils, such as strip, objdump and strings.

A devkit is a collection of tools native to the host. A devkit can be selected or disabled for a target. An example of a devkit is the doctools devkit, which provides tools (like doxygen) for building documentation.

A rootstrap is a root file system for the target device. The Maemo SDK provides root file systems for both targets (X86 and ARMEL) inside Scratchbox. Note that the user's home directory is shared for all targets. The /tmp directory is shared for all targets and also with the host.

From Scratchbox's point of view, the Maemo SDK is a set of preconfigured targets and root file systems. One set is provided for both X86 and ARMEL architectures on top of a working Scratchbox installation.

[edit] Development in the Maemo SDK

The Maemo SDK provides all of its development tools inside Scratchbox. Also the UI framework is started with a single command, af-sb-init, run within Scratchbox. However, it needs a secondary X server of proper size and bit-depth to be displayed on.

As an exception to the rule, you must start the Xserver, such as Xephyr on the host Linux environment, not inside Scratchbox.

[edit] Scratchbox Development Tools

As the Scratchbox environment is practically a full GNU/Linux system, it includes the standard GNU/Linux development tools. Debugging is performed with tools like gdb, valgrind, ltrace and strace. Performance profiling can be performed with tools like htop, oprofile and time. Compiling is done with the GCC toolchain. Some of these tools offer graphical user interfaces, which can also be used. Naturally, this is not a comprehensive list of the tools, and if the tools shipped with the SDK do not suit your needs or personal preferences, most utilities can be easily run practically unchanged in Scratchbox.

[edit] Other Programming Languages

Currently C is the only official programming language for Maemo. But thanks to the community, the Python scripting language also has good support in the form of pymaemo. C++ support for Scratchbox is also available.

[edit] Installing the SDK

Before continuing, review the installation instructions of the Maemo SDK.

The kernel must support the binfmt_misc feature in order for the instruction emulator in Scratchbox to work properly. Because it is usually built as a module, verify that the module is loaded in Linux (no root access needed):

user@system:~$ lsmod | grep binfmt
binfmt_misc 12936 0

If you do not see a line of output, try to execute

modprobe binfmt_misc

as root (or with sudo). If this still does not work, either locate the module elsewhere, or recompile the kernel. Most Debian-based systems (Debian, Ubuntu) include the module, unless you have built your own kernel, you should encounter no problems. The feature may also be directly built inside the kernel instead of being a module.

Install a pseudo X server to act as an X client to the real system in order to run application developed after installing the SDK. You have a certain amount of freedom to choose the most suitable option to achieve this, but this material assumes that you are using Xephyr, a Kdrive-based X server/client that can emulate 16-color depth for its clients even while acting as a client to an 24-bit depth real X server. Xephyr also implements modern X protocol extensions.

The concept of having a program that is both X server and a client may seem weird, but it is a tested technology and works quite well.

To install Xephyr on a Debian-based Linux:

  • Issue the command
    sudo apt-get install xserver-xephyr
    on your real Linux system.
  • Verify installation status by issuing the command
    dpkg -l | grep xephyr
    (as non-root).

As mentioned before, the Maemo SDK uses Scratchbox as the cross-compilation environment. Therefore, you must install Scratchbox first before attempting to install the SDK. The preferred way to install Scratchbox and the SDK is to use the automated installation scripts, though manual installation steps are also provided. Detailed instructions are found on the maemo.org wiki.

[edit] Testing SDK Installation

[edit] Testing Scratchbox

The following shows how to create a small non-graphical Hello World program to verify that the Scratchbox environment works: helloworld.c

/**
 * helloworld.c
 *
 * This maemo code example is licensed under a MIT-style license,
 * that can be found in the file called "License" in the same
 * directory as this file.
 * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.
 *
 * Simple standard I/O (printf)-based Hello World that we can use to
 * test our toolchains.
 */
 
#include <stdio.h> /* printf */
 
/* main implementation */
int main(int argc, char** argv) {
 
  printf("Hello world\n");
 
  /* In Linux, each process upon termination must set its exit code.
     Exit code 0 means success to whoever executed this program. It
     is routinely used inside scripts to test whether running some
     program succeeded or not. Other exit codes mean failure. Each
     program is free to use different non-zero codes to signify
     different kinds of failures. These are normally listed in the
     manual page for the program (since there is no standard). If you
     forget to set your exit code, it will be undefined. */
  return 0;
}

First, verify that the proper directory is chosen by using pwd (print working directory). At this point, the work directory should be your home directory:

[sbox-FREMANTLE_X86: ~] > pwd
/home/user

Then, start an editor and write a small hello world program (you may use the above code listing as a template if you wish):

[sbox-FREMANTLE_X86: ~] > nano helloworld.c

It is also possible to use the vi (Visual Interactive) editor inside Scratchbox. You can install your own favourite editor inside Scratchbox (with the debian-devkit), but the following examples will use nano, because it is the easiest to start with. If you want to learn vi, your best course of action is searching for "vi tutorial" with your favourite search engine. There are lots of them to be found. To understand why vi can be considered "strange", it is useful to know its history first. Using vi is fully optional.

[sbox-FREMANTLE_X86: ~] > gcc -Wall -g helloworld.c -o helloworld
[sbox-FREMANTLE_X86: ~] > ls -F hello*
helloworld* helloworld.c

GCC's -g option tells the compiler to add debugging symbols to the generated output file. -Wall will tell the compiler to enable most of the syntax and other warnings that the source code could trigger. -o helloworld tells gcc to output the resulting binary with the filename of helloworld.

The -F option to ls is mainly useful when working with a non-color terminal (for example paper) to indicate the type of different files. The asterisk after helloworld signifies that the file is executable.

[sbox-FREMANTLE_X86: ~] > ./helloworld
Hello world

Running the binary should not produce any surprises.

[sbox-FREMANTLE_X86: ~] > file helloworld
helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.6.0, dynamically linked (uses shared libs), not stripped

The file tool is a generic utility that loads some bytes from the start of the given file and then uses its internal database to decode what type of file it is. In this case, it will correctly decode the file as a X86 format binary file.

[sbox-FREMANTLE_X86: ~] > ldd helloworld
   linux-gate.so.1 =>  (0xffffe000)
   libc.so.6 => /lib/libc.so.6 (0xb7e9f000)
   /lib/ld-linux.so.2 (0xb7fd2000)
[sbox-FREMANTLE_X86: ~] > ls -l /lib/libc.so.6
lrwxrwxrwx  1 user user 11 Nov 12 15:52 /lib/libc.so.6 -> libc-2.5.so
[sbox-FREMANTLE_X86: ~] > ls -l /lib/libc-2.5.so
-rwxr-xr-x  1 user user 1213256 Sep  7 13:28 /lib/libc-2.5.so

On the left are the names of dynamic libraries that the executable uses, and on the right are the files where the libraries reside on the system when executing the program. Next use ls to check the exact version of the C library that the SDK uses with the "long listing format" -l option. Running these commands using the ARMEL target yields more or less the same results. N.B. The linux-gate.so.1 library is a so-called hack to support a certain way of doing system calls on the X86 architecture, and is not always present on newer systems.

When comparing the version of libc used on the real system with ls -l, it will probably show a difference (in version numbers). This means that the executables that were built inside Scratchbox use libraries that are also inside Scratchbox. This also means we have a stable development platform, which is very important, especially when working on a team where each member has their own Linux installation which they may or may not have customized. This might not seem very important at this stage, but when encountering all the different tools that are used in free software development, this feature of Scratchbox will come in handy.

Scratchbox does not contain any logic to emulate the kernel (or to use a different kernel for running programs inside Scratchbox). The only easy possibility for this is using the sbrsh CPU-transparency option.

[edit] vi

You can also use the vi (Visual Interactive) editor inside Scratchbox. You can install your own favorite editor inside Scratchbox (with the debian-devkit), but the following examples will use nano, since it is the easiest to start with. If you want to learn vi, search for "vi tutorial" with your favorite search engine. There are lots of them to be found. To understand why vi can be considered "strange", it is useful to know its history first. Using vi is fully optional. It is common for people who are new to vi to get stuck in it; if you find yourself in this situation, a way to exit (without writing the file) is to press type <escape>:qall!<enter>.

The vi that is commonly installed on Linux systems is really vim (VI iMproved), which is a more user-friendly version of vi, including syntax hilighting and all kinds of improvements. Scratchbox has a program called vimtutor installed to help you learn how to use vi interactively.

It is also fairly simple to use existing editors. /scratchbox/users/x/home/x/ is the home directory of user x when accessing it from the real Linux desktop. Ubuntu comes with Gedit, which is a fairly good graphical editor that also supports syntax highlighting and multiple tabs for editing multiple files at the same time.

And as a final note, emacs can also be used.

Here is how to do use it:

  • Start emacs outside of Scratchbox
  • In emacs, use M-x server-start
  • Inside Scratchbox, use the emacsclient filename to open the file for editing in your emacs

[edit] Writing GUI Hello World

The following example shows how to write the first GUI program. Note that the example only uses the GTK+ library and does not utilise the widgets and coding style provided by the platform. That will be discussed later.

gtk_helloworld-1.c

/**
 * gtk_helloworld-1.c
 *
 * This maemo code example is licensed under a MIT-style license,
 * that can be found in the file called "License" in the same
 * directory as this file.
 * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.
 *
 * A simple GTK+ Hello World. You need to use Ctrl+C to terminate
 * this program since it doesn't implement GTK+ signals (yet).
 */
 
#include <stdlib.h> /* EXIT_* */
/* Introduce types and prototypes of GTK+ for the compiler. */
#include <gtk/gtk.h>
 
int main(int argc, char** argv) {
 
  /* We'll have two references to two GTK+ widgets. */
  GtkWindow* window;
  GtkLabel* label;
 
  /* Initialize the GTK+ library. */
  gtk_init(&argc, &argv);
 
  /* Create a window with window border width of 12 pixels and a
     title text. */
  window = g_object_new(GTK_TYPE_WINDOW,
    "border-width", 12,
    "title", "Hello GTK+",
    NULL);
 
  /* Create the label widget. */
  label = g_object_new(GTK_TYPE_LABEL,
    "label", "Hello World!",
    NULL);
 
  /* Pack the label into the window layout. */
  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(label));
 
  /* Show all widgets that are contained by the window. */
  gtk_widget_show_all(GTK_WIDGET(window));
 
  /* Start the main event loop. */
  g_print("main: calling gtk_main\n");
  gtk_main();
 
  /* Display a message to the standard output and exit. */
  g_print("main: returned from gtk_main and exiting with success\n");
 
  /* The C standard defines this condition as EXIT_SUCCESS, and this
     symbolic macro is defined in stdlib.h (which GTK+ will pull in
     in-directly). There is also a counter-part for failures:
     EXIT_FAILURE. */
  return EXIT_SUCCESS;
}

Build your program:

[sbox-FREMANTLE_X86: ~] > gcc -Wall -g gtk_helloworld-1.c -o gtk_helloworld-1
gtk_helloworld-1.c:15:21: gtk/gtk.h: No such file or directory
gtk_helloworld-1.c: In function `main':
gtk_helloworld-1.c:20: error: `GtkWindow' undeclared (first use in this function)
gtk_helloworld-1.c:20: error: (Each undeclared identifier is reported only once
gtk_helloworld-1.c:20: error: for each function it appears in.)
gtk_helloworld-1.c:20: error: `window' undeclared (first use in this function)
gtk_helloworld-1.c:21: error: `GtkLabel' undeclared (first use in this function)
gtk_helloworld-1.c:21: error: `label' undeclared (first use in this function)
gtk_helloworld-1.c:24: warning: implicit declaration of function `gtk_init'
gtk_helloworld-1.c:28: warning: implicit declaration of function `g_object_new'
gtk_helloworld-1.c:28: error: `GTK_TYPE_WINDOW' undeclared (first use in this function)
gtk_helloworld-1.c:34: error: `GTK_TYPE_LABEL' undeclared (first use in this function)
gtk_helloworld-1.c:39: warning: implicit declaration of function `gtk_container_add'
gtk_helloworld-1.c:39: warning: implicit declaration of function `GTK_CONTAINER'
gtk_helloworld-1.c:39: warning: implicit declaration of function `GTK_WIDGET'
gtk_helloworld-1.c:42: warning: implicit declaration of function `gtk_widget_show_all'
gtk_helloworld-1.c:45: warning: implicit declaration of function `g_print'
gtk_helloworld-1.c:46: warning: implicit declaration of function `gtk_main'


This does not look at all promising. The source code started with #include, and you need to tell the compiler where to look for that critical GTK+ header file. The compiler probably also needs some special flags to be able to use the correct compilation settings for building GTK+ software.

To help you decide which flags to use we provide a tool called pkg-config, which is a simple program that provides a unified interface to output compiler, linker flags and library version numbers. Use pkg-config manually for the time being.

[sbox-FREMANTLE_X86: ~] > pkg-config --list-all | sort
.. listing cut to include only relevant libraries ..
dbus-glib-1    dbus-glib - GLib integration for the free desktop message bus
gconf-2.0      gconf - GNOME Config System.
gdk-2.0        GDK - GIMP Drawing Kit (x11 target)
gdk-pixbuf-2.0 GdkPixbuf - Image loading and scaling
glib-2.0       GLib - C Utility Library
gnome-vfs-2.0  gnome-vfs - The GNOME virtual file-system libraries
gtk+-2.0       GTK+ - GIMP Tool Kit (x11 target)
hildon-1       hildon - Hildon widgets library
hildon-fm-2    hildon-fm - Hildon file management widgets
pango          Pango - Internationalized text handling
x11            X11 - X Library

pkg-config also has some other useful commands:

[sbox-FREMANTLE_X86: ~] > pkg-config --modversion gtk+-2.0
2.10.12


[sbox-FREMANTLE_X86: ~] > pkg-config --cflags gtk+-2.0
-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/pango-1.0 -I/usr/include/glib-2.0
-I/usr/lib/glib-2.0/include -I/usr/include/freetype2
-I/usr/include/libpng12

In this version of GTK+, all these commands are -I options that tell the compiler which additional directories to check for system header files in addition to the default ones.

[sbox-FREMANTLE_X86: ~] > pkg-config --libs gtk+-2.0
-lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm
-lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2
-ldl -lglib-2.0

When linking the application, the linker has to be told which libraries to link against. In fact, the whole program linking phase will fail (as shown below) without this information.

Now compile the software again, and this time use the compilation flags that pkg-config provides:

[sbox-FREMANTLE_X86: ~] > gcc -Wall -g gtk_helloworld-1.c  \
 `pkg-config --cflags gtk+-2.0` -o gtk_helloworld-1
/var/tmp/ccQ14x4c.o: In function `main':/home/user/gtk_helloworld-1.c:24:
 undefined reference to `gtk_init'
:/home/user/gtk_helloworld-1.c:28: undefined reference to `gtk_window_get_type'
:/home/user/gtk_helloworld-1.c:28: undefined reference to `g_object_new'
:/home/user/gtk_helloworld-1.c:34: undefined reference to `gtk_label_get_type'
:/home/user/gtk_helloworld-1.c:34: undefined reference to `g_object_new'
:/home/user/gtk_helloworld-1.c:39: undefined reference to `gtk_widget_get_type'
:/home/user/gtk_helloworld-1.c:39: undefined reference to `g_type_check_instance_cast'
:/home/user/gtk_helloworld-1.c:39: undefined reference to `gtk_container_get_type'
:/home/user/gtk_helloworld-1.c:39: undefined reference to `g_type_check_instance_cast'
:/home/user/gtk_helloworld-1.c:39: undefined reference to `gtk_container_add'
:/home/user/gtk_helloworld-1.c:42: undefined reference to `gtk_widget_get_type'
:/home/user/gtk_helloworld-1.c:42: undefined reference to `g_type_check_instance_cast'
:/home/user/gtk_helloworld-1.c:42: undefined reference to `gtk_widget_show_all'
:/home/user/gtk_helloworld-1.c:45: undefined reference to `g_print'
:/home/user/gtk_helloworld-1.c:46: undefined reference to `gtk_main'
:/home/user/gtk_helloworld-1.c:49: undefined reference to `g_print'
collect2: ld returned 1 exit status

The command above may be new to you, if you have not used UNIX command shells. This is a backtick expansion, an operation where the shell starts another shell only to execute the text inside the backticks. In this case, start another shell to run `pkg-config --cflags gtk+-2.0`. Normal output from the commands is then read into the main shell and the output is replaced into the location where the backticks were. N.B. Use the backtick character (`) or falling accent. Do not use a rising accent (´) or a single quote or apostrophe ('). In some keyboard layouts, you can get the backtick character to appear by pressing first the backtic and then the space bar.

An alternative operation is $(pkg-config ..), which corresponds to the backtick but is less portable across antique UNIX shells. Choosing between these is a matter of taste.

GCC prints very different errors this time. These errors come from ld, which is the binary code linker in Linux systems and complains about missing symbols (the undefined references). Obviously something is still missing.

You must tell the linker where to find the missing symbols. Because this is the linker and not the compiler that we are talking about, the missing symbols are in the library files.

To fix the problem (again using backticks), pkg-config --libs can be used:

[sbox-FREMANTLE_X86: ~] > gcc -Wall -g gtk_helloworld-1.c  \
 `pkg-config --cflags --libs gtk+-2.0` -o gtk_helloworld-1
[sbox-FREMANTLE_X86: ~] >

The next step is to repeat the basic commands that you used before with the non-GUI hello world:

[sbox-FREMANTLE_X86: ~] > ls -l gtk_helloworld-1
-rwxrwxr-x  1 user user 16278 Nov 20 00:22 gtk_helloworld-1
[sbox-FREMANTLE_X86: ~] > file gtk_helloworld-1
gtk_helloworld-1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.6.0, dynamically linked (uses shared libs), not stripped
[sbox-FREMANTLE_X86: ~] > ldd gtk_helloworld-1
  linux-gate.so.1 =>  (0xffffe000)
  libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0 (0xb7c4c000)
  libgdk-x11-2.0.so.0 => /usr/lib/libgdk-x11-2.0.so.0 (0xb7bc8000)
  libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0 (0xb7bad000)
  libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0 (0xb7b97000)
  libm.so.6 => /lib/libm.so.6 (0xb7b71000)
  libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0xb7b68000)
  libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0xb7b2b000)
  libcairo.so.2 => /usr/lib/libcairo.so.2 (0xb7ab5000)
  libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0xb7a7a000)
  libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0xb7a76000)
  libdl.so.2 => /lib/libdl.so.2 (0xb7a71000)
  libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0xb79dd000)
  libc.so.6 => /lib/libc.so.6 (0xb78b2000)
  libX11.so.6 => /usr/lib/libX11.so.6 (0xb77bd000)
  libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0xb77b8000)
  libXtst.so.6 => /usr/lib/libXtst.so.6 (0xb77b3000)
  libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0xb7788000)
  libXext.so.6 => /usr/lib/libXext.so.6 (0xb777a000)
  libXrender.so.1 => /usr/lib/libXrender.so.1 (0xb7771000)
  libXi.so.6 => /usr/lib/libXi.so.6 (0xb7769000)
  libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0xb7762000)
  libXcursor.so.1 => /usr/lib/libXcursor.so.1 (0xb7759000)
  /lib/ld-linux.so.2 (0xb7fc3000)
  libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0xb772b000)
  libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0xb76c6000)
  libz.so.1 => /usr/lib/libz.so.1 (0xb76b7000)
  libpng12.so.0 => /usr/lib/libpng12.so.0 (0xb7692000)
  libXau.so.6 => /usr/lib/libXau.so.6 (0xb768f000)
  libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0xb7689000)
  libexpat.so.1 => /usr/lib/libexpat.so.1 (0xb7669000)

As you can see from the last ldd listing, this simple Hello World requires several other libraries to run. The program itself only requires GTK+, but GTK+ needs GDK and all the other libraries that were covered in the introduction. Those libraries in turn need other libraries and so on.

This is almost the full list of all required libraries to run. Modern UNIX systems (and Linux) can also load other libraries on demand (called runtime dynamic module loading).

Perhaps you are wondering why writing a simple Hello World is so demanding. It is actually much simpler in real life. This chapter simply introduces and solves various problems that you may encounter in actual situations.

You need all of these tools later on when starting the packaging of the software.

[edit] Running GUI Hello World

Let's try to execute Hello World inside Scratchbox:

[sbox-FREMANTLE_X86: ~] > ./gtk_helloworld-1
gtk_helloworld-1[4759]: GLIB WARNING ** Gtk - cannot open display:
[sbox-FREMANTLE_X86: ~] > echo $DISPLAY

GTK+ seems unable to open connection to the X server. To verify this, display the contents of the DISPLAY environmental variable; indeed, the variable is empty. If the DISPLAY variable contains :0.0, the value originates in the graphical session and was copied into Scratchbox. Clients try to connect to the real X server and probably fail during authentication.

[edit] Starting Virtual X Server (Xephyr)

Run Xephyr outside the Scratchbox environment:

$ Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac -kb &

[edit] Directing Client to Virtual Server

Now that there is an X server running, switch back to Scratchbox.

The first step is to set the environmental variable so that the X server knows to use a local domain socket, and tell all X clients to connect to Display number 2, since that is where Xephyr started:

[sbox-FREMANTLE_X86: ~] > export DISPLAY=:2
[sbox-FREMANTLE_X86: ~] > ./gtk_helloworld-1
main: calling gtk_main
[Ctrl+c]

Use Ctrl+C to terminate the program because it does not implement any graphical methods for closing.

N.B. The DISPLAY needs to be set correctly on each Scratchbox login (or when switching targets).

Since you did not start a window manager for the X server, you cannot control Hello World with the mouse. Use Ctrl+C to terminate Hello World; you will start it again in a moment.

To quickly detach the foreground process from the shell and continue running the process in the background, press Ctrl+Z and then use the shell command bg. The process is "paused" between these two steps.

[edit] Starting Application Framework

The next step is to have a graphical environment that will implement a nicer graphical screen. For this, a series of clients will be started, each of which have a specific role. These were introduced before.

To start the UI Framework, you can use a handy script that comes with the SDK:

[sbox-FREMANTLE_X86: ~] > af-sb-init.sh start

The start and stop parameters are used to start and stop the graphical environment. If everything works, it should show a screen resembling this one:

Screenshot of SDK user interface
SDK UI

[edit] Running Hello World in Application Framework

While the UI framework is running, the Hello World can be started again

[sbox-FREMANTLE_X86: ~] >./gtk_helloworld-1

Screenshot of test application showing ‘Hello World!’ in the centre of an unthemed window
Hello world

Because there now is a window manager running, the client gets much larger window to draw in. GTK+ scales the widget accordingly (there is only one widget in the program).

The screen still looks a bit off. If the application is closed by pressing the X in the top-right corner, you can see that the Hello World disappears from the screen. Because no signals have been implemented yet and thus there is nothing to handle window destruction, the Hello World application is only hidden. It is still running (as can be seen in the sbox terminal emulator, since the shell does not display its prompt). Stop the Hello World program with Ctrl+C.

The next step shows how to use an SDK utility script called run-standalone.sh. Its job is to set up the correct environment variables for themes and communication for the command that is given to it as its command line parameter.

[sbox-FREMANTLE_X86: ~] >run-standalone.sh ./gtk_helloworld-1
Screenshot of test application showing ‘Hello World!’ in the centre of a themed window
Themed Hello world

The screen is still a bit off (there are no borders around the main GtkLabel widget), but already looks better. The text is scaled to be more in sync with the other text sizes and the color is also in sync with the platform color (it is not gray anymore).