|
|
(28 intermediate revisions not shown) |
Line 1: |
Line 1: |
- | = Development Environment =
| + | *[[{{PAGENAME}}/Maemo_SDK| Software Development Kit]] |
| + | *[[{{PAGENAME}}/Maemo_Programming_Environments|Programming Environments]] |
| + | *[[Documentation/Maemo PC Connectivity Tutorial|PC Connectivity]] |
| + | *[[{{PAGENAME}}/Maemo_Flasher-3.5|Flasher-3.5]] |
| + | *[[{{PAGENAME}}/Maemo_SDK_Virtual_Images|SDK Virtual Images]] |
| + | *[[Eclipse integration]] |
| | | |
- | The development environment for Maemo running on the desktop is called '''Maemo SDK'''. It will only install and run on a Linux operating system. Supported Linux distributions for Maemo SDK are currently Debian and Ubuntu, but installing Maemo SDK is also possible on other distributions.
| + | [[Category:Development]] |
- | | + | [[Category:Documentation]] |
- | = Maemo Software Development Kit =
| + | [[Category:Fremantle]] |
- | | + | |
- | 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.
| + | |
- | | + | |
- | | + | |
- | ==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 suport 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.
| + | |
- | | + | |
- | 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.
| + | |
- | | + | |
- | 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 />
| + | |
- | | + | |
- | ==Scratchbox==
| + | |
- | Scratchbox is a specially packaged "sandbox" environment, providing the necessary tools and also isolating the development efforts from the real Linux system. Scratchbox also makes it easy to perform cross-compiling, which means building the software into a binary format that is executable in 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 ([http://bellard.org/qemu 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 [http://scratchbox.org project website].
| + | |
- | | + | |
- | This material discusses only the Scratchbox capabilities that are necessary to use the Maemo SDK.
| + | |
- | | + | |
- | | + | |
- | ===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.
| + | |
- | | + | |
- | The ''target'' inside Scratchbox contains a root file system that is being worked on. When a new target inside Scratchbox is created, a ''toolchain'' must be specified for it. Using this toolchain, applications are built for the target. Examples of a ''target'' are X86 and ARMEL, which are 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. One and only one toolchain must be selected for every Scratchbox target.
| + | |
- | | + | |
- | ''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''), it 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 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.
| + | |
- | | + | |
- | 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.
| + | |
- | | + | |
- | | + | |
- | ==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, ''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, the X server such as [http://www.freedesktop.org/wiki/Software/Xephyr Xephyr] must be started on the host Linux environment, instead of being started inside Scratchbox. The use of Xephyr is described in Section [localhost#sec:testing_installation 3.4].
| + | |
- | | + | |
- | | + | |
- | ===Development Tools on 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===
| + | |
- | 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 =
| + | |
- | | + | |
- | Before continuing, the installation instructions (link) of the Maemo SDK should be reviewed.
| + | |
- | | + | |
- | There is a special feature that the kernel on your development computer needs to support in order for the instruction emulator in sbox to work properly. This is the binfmt_misc feature. It is normally built as a module, so verify that it is loaded in Linux (no root access needed for this):
| + | |
- | | + | |
- | user@system:~$ lsmod | grep binfmt
| + | |
- | binfmt_misc 12936 0
| + | |
- | | + | |
- | If you do not see a line of output, attempt to do a modprobe binfmt_misc as root (or with sudo). If this still does not work, you will have to find the module somewhere, or even recompile the kernel. On most Debian-based systems (Debian, Ubuntu), the module is included, so there should not be any problems unless you have built your own kernel. It is also possible that the feature has been built inside the kernel directly instead of a module.
| + | |
- | | + | |
- | Also a pseudo X server should be installed to act as an X client to the real system. It will be necessary for running the applications that you are developing after installing the SDK.
| + | |
- | | + | |
- | There are a few options for this purpose, but this material will cover the usage of Xephyr. Xephyr is a Kdrive-based X server/client that can emulate 16-color depth for its clients even if it is acting as a client to an 24-bit depth real X server. It also implements modern X protocol extensions.
| + | |
- | | + | |
- | The concept of having a program that is both X server and a client may seem weird. However, there is no reason to worry, as it is a tested technology and works quite well. If, on the other hand, it does not make any sense, revisit the X Window System introduction in the previous chapter.
| + | |
- | | + | |
- | 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, Maemo SDK uses scratchbox as the cross-compilation environment. Therefore, it is essential to 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 at [link to installation instructions].
| + | |
- | | + | |
- | = Testing SDK Installation =
| + | |
- | | + | |
- | == Testing Scratchbox ==
| + | |
- | 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>
| + | |
- | <span>''<span><font color="#9A1900"> * helloworld.c</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> *</font></span>''</span>
| + | |
- | <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>
| + | |
- | <span>''<span><font color="#9A1900"> * directory as this file.</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> *</font></span>''</span>
| + | |
- | <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>
| + | |
- | <span>''<span><font color="#9A1900"> */</font></span>''</span>
| + | |
- |
| + | |
- | <span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000"><stdio.h></font></span> <span>''<span><font color="#9A1900">/* printf */</font></span>''</span>
| + | |
- |
| + | |
- | <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>
| + | |
- |
| + | |
- | <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>
| + | |
- |
| + | |
- | <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:
| + | |
- | | + | |
- | [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
| + | |
- | | + | |
- | nano is a GNU version of "pico" editor, which is a simple text file editor. Use Control+character to execute the commands listed on the bottom of the screen. WriteOut means "save". You may also use vi or an external editor to the SDK environment (see below for hints on using vi and emacs).
| + | |
- |
| + | |
- | [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 (e.g. paper) to indicate the type of different files. The asterisk after helloworld signifies that the file is an executable. <br />
| + | |
- | | + | |
- | [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 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.
| + | |
- |
| + | |
- | [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
| + | |
- | | + | |
- | | + | |
- | The names of dynamic libraries that the executable uses will be shown on the left-hand column, and the files where the libraries live on the system if executing the program will be shown on the right-hand column. After that, use ls to check out the exact version of the C library that is used in the SDK by using the "long listing format" -l option (running these commands using the ARMEL target would yield more or less the same results). N.B. 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 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 sbox). The only easy possibility for this is using the sbrsh CPU-transparency option.
| + | |
- | | + | |
- | ===vi===
| + | |
- | 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.
| + | |
- | | + | |
- | 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 sbox
| + | |
- | * In emacs, use M-x server-start
| + | |
- | * Inside sbox use emacsclient filename to open the file for editing in your emacs
| + | |
- | | + | |
- | ==Writing GUI Hello World==
| + | |
- | The following example shows how to write the first GUI program. NOTE: Only the GTK+ library is used here, meaning that the platform provided widgets and coding style are not utilized. That will be discussed soon. gtk_helloworld-1.c
| + | |
- | | + | |
- | <tt><span>''<span><font color="#9A1900">/**</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> * gtk_helloworld-1.c</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> *</font></span>''</span>
| + | |
- | <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>
| + | |
- | <span>''<span><font color="#9A1900"> * directory as this file.</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> *</font></span>''</span>
| + | |
- | <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>
| + | |
- | <span>''<span><font color="#9A1900"> */</font></span>''</span>
| + | |
- |
| + | |
- | <span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000"><stdlib.h></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>
| + | |
- | <span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000"><gtk/gtk.h></font></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>
| + | |
- |
| + | |
- | <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>
| + | |
- | GtkLabel<span><font color="#990000"><nowiki>*</nowiki></font></span> label<span><font color="#990000"><nowiki>;</nowiki></font></span>
| + | |
- |
| + | |
- | <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">(&</font></span>argc<span><font color="#990000">,</font></span> <span><font color="#990000">&</font></span>argv<span><font color="#990000">);</font></span>
| + | |
- |
| + | |
- | <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>
| + | |
- | 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>
| + | |
- | <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>
| + | |
- | <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>
| + | |
- | NULL<span><font color="#990000">);</font></span>
| + | |
- |
| + | |
- | <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>
| + | |
- | <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>
| + | |
- | NULL<span><font color="#990000">);</font></span>
| + | |
- |
| + | |
- | <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>
| + | |
- |
| + | |
- | <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>
| + | |
- |
| + | |
- | <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>
| + | |
- | <span>'''<span><font color="#000000">gtk_main</font></span>'''</span><span><font color="#990000">();</font></span>
| + | |
- |
| + | |
- | <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>
| + | |
- |
| + | |
- | <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>
| + | |
- | <span>''<span><font color="#9A1900"> in-directly). There is also a counter-part for failures:</font></span>''</span>
| + | |
- | <span>''<span><font color="#9A1900"> EXIT_FAILURE. */</font></span>''</span>
| + | |
- | <span>'''<span><font color="#0000FF">return</font></span>'''</span> EXIT_SUCCESS<span><font color="#990000"><nowiki>;</nowiki></font></span>
| + | |
- | <span><font color="#FF0000">}</font></span></tt>
| + | |
- | | + | |
- | 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'
| + | |
- | | + | |
- | | + | |
- | As you can see, this does not look at all promising. At the start of the source code, there was an #include. The compiler needs to be told where it should look for that critical GTK+ header file. It is also quite likely that some special flags need to be passed to the compiler in order for it to use the proper compilation settings when building GTK+ software. How do we decide which flags to use?
| + | |
- | | + | |
- | This is where a tool called pkg-config comes to the rescue. It is a simple program that provides a unified interface to output compiler, linker flags and library version numbers. Its use will be discussed later, when starting the automating of the building process. For now, pkg-config will be used manually.
| + | |
- |
| + | |
- | [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 commands that will be useful: <
| + | |
- |
| + | |
- | [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
| + | |
- | | + | |
- | | + | |
- | As you can see, there are many. With this version of GTK+, all of them are -I options. They are used to tell the compiler which additional directories to check for system header files in addition to the defaults.
| + | |
- |
| + | |
- | [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 it is time to try and compile the software again, this time using the compilation flags that pkg-config provides:
| + | |
- | | + | |
- | | + | |
- | <nowiki>
| + | |
- | [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
| + | |
- | </nowiki>
| + | |
- | | + | |
- | | + | |
- | The command above might seem somewhat strange to someone not having used UNIX shell commands before. What is happening here is backtick expansion. It is an operation where the shell will start another shell to execute just the commands inside the backticks. In this case, another shell is started to run "pkg-config cflags gtk+-2.0". Normal output from the commands is then read into the main shell, and this output replaces the text between the backticks. NOTE: It is very important to use the ` character and not ', nor the other quote character that might be used in a Swedish keyboard layout (also used in Finland). In some keyboard layouts, it will be necessary to press space after the backtick since it is also used for character composition (try backtick and the letter 'a').
| + | |
- | | + | |
- | Something like $(pkg-config ..) might also be encountered. This is the same operation as backtick. However, backtick is more portable across antique UNIX shells. Nowadays, the choice comes down to personal preference.
| + | |
- | | + | |
- | The errors printed by gcc are quite different this time. These errors come from ld, which is the binary code linker in Linux systems and it is complaining about missing symbols (the undefined references). Obviously something is still missing.
| + | |
- | | + | |
- | The linker needs to be told where to find the missing symbols. Since it all about the linker and not the compiler, the missing symbols are found in the library files. To fix the problem (again, with backticks), pkg-config libs can be used:
| + | |
- |
| + | |
- | [sbox-FREMANTLE_X86: ~] > gcc -Wall -g gtk_helloworld-1.c \
| + | |
- | `pkg-config --cflags gtk+-2.0` -o gtk_helloworld-1 \
| + | |
- | `pkg-config --libs gtk+-2.0`
| + | |
- | [sbox-FREMANTLE_X86: ~] >
| + | |
- | | + | |
- | | + | |
- | The order and placement of the pkg-config commands above is important: the cflags need to be placed as early as possible, but the libs must come last (this does matter in some problematic linking scenarios).
| + | |
- | | + | |
- | The next step is to repeat the basic commands that were 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 can be seen from the last ldd listing, this simple Hello World manages to require quite a number of other libraries to run. The program only directly 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.
| + | |
- | | + | |
- | So, what is seen here is almost the full list of all required libraries to run. Almost, because modern UNIX systems (and Linux) can also load libraries on demand (called runtime dynamic module loading).
| + | |
- | | + | |
- | This might make one wonder why writing a simple Hello World program is this painful. It is actually much simpler in real life. The reason why this chapter introduces the various errors is that they will be encountered in actual situations quite early on. This chapter serves as a reference to some possible errors, and (hopefully) also show you a solution.
| + | |
- | | + | |
- | All of these tools will be needed later on when starting the packaging of the software and they will be covered in full detail later in this document.
| + | |
- | | + | |
- | == Running GUI Hello World ==
| + | |
- | Let's try to execute our nice Hello World (inside sbox):
| + | |
- | | + | |
- | [sbox-FREMANTLE_X86: ~] > ./gtk_helloworld-1
| + | |
- | gtk_helloworld-1[4759]: GLIB WARNING ** Gtk - cannot open display:
| + | |
- | [sbox-FREMANTLE_X86: ~] > echo $DISPLAY
| + | |
- | | + | |
- | | + | |
- | Seems that GTK+ is having problems opening a connection to the X server. This can be verified by displaying the contents of the DISPLAY environment variable, and indeed, it comes out empty. If the DISPLAY variable contains :0.0, it means that the value has been copied from the real graphical session into sbox, and clients will try to connect to the real X server (and probably fail during authentication).
| + | |
- | | + | |
- | Xephyr was installed in the previous chapter, so now it has to be started so that it can be used as the server for all clients running inside the Scratchbox session.
| + | |
- | | + | |
- | == Starting Virtual X Server (Xephyr) ==
| + | |
- | | + | |
- | Open another terminal emulator (do not close your sbox session).
| + | |
- | | + | |
- | 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. This means that the networking environment should be treated with extreme caution, so that rogue users will not target your Xephyr with their own clients.
| + | |
- | | + | |
- | The last parameter (-extension Composite) disables the Composite extension.
| + | |
- | | + | |
- | When Xephyr starts, it will connect 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 will have one screen, and it will be filled by the default X server background pattern (a black and white checkerboard).
| + | |
- | | + | |
- | N.B. The terminal emulator (more specifically, the shell that the emulator started) is waiting for Xephyr to end. If all the graphical applications running in the SDK ever need to be killed, it can be done easily by just closing Xephyr. This will leave the daemons running inside sbox (D-Bus and friends). Normally this is not a good idea. To ask the foreground process to terminate itself, use Ctrl+C. Inside sbox, this same technique can be used to terminate a graphical client that was started from the command line (as we will show you shortly).
| + | |
- | | + | |
- | == Directing Client to Virtual Server ==
| + | |
- | | + | |
- | Now that there is an X server running, it is time to switch back to sbox.
| + | |
- | | + | |
- | 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 the Xephyr was just started:
| + | |
- | | + | |
- | <nowiki>
| + | |
- | [sbox-FREMANTLE_X86: ~] > export DISPLAY=:2
| + | |
- | [sbox-FREMANTLE_X86: ~] > ./gtk_helloworld-1
| + | |
- | main: calling gtk_main
| + | |
- | [[Ctrl+c]]
| + | |
- | </nowiki>
| + | |
- | | + | |
- | | + | |
- | The program has to be terminated with Ctrl+C, since it does not implement any graphical methods for closing. NOTE: The DISPLAY environment variable needs to be set correctly on each sbox login (or target switch).
| + | |
- | | + | |
- | Since the window manager is missing (none were started for the X server), the Hello World program cannot be controlled with the mouse. Kill it with Ctrl+C for now. (We'll restart it in a moment.)
| + | |
- | | + | |
- | To quickly detach the foreground process from the shell and continue running it in the background, use the Ctrl+Z key combination and then use the shell command bg. Between those two steps the process will be "paused".
| + | |
- | | + | |
- | == Starting Application Framework ==
| + | |
- | | + | |
- | The next step is to have a nice graphical environment - one that is a lot nicer than the default X environment. 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:
| + | |
- | | + | |
- | [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, you should see a screen resembling this one:
| + | |
- | | + | |
- | | + | |
- | [[Image:UI-startup.png|400px]]
| + | |
- | | + | |
- | ==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
| + | |
- | | + | |
- | [[Image:helloworld-without-theme.png|400px]]
| + | |
- | | + | |
- | 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). N.B. The screen still looks a bit off. If the application is closed by pressing the X in the top-right corner, it can be seen 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 with Ctrl+c.
| + | |
- | | + | |
- | Next step shows how to use an SDK utility script called run-standalone.sh. Its job is to set up correct environmental 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
| + | |
- | | + | |
- | [[Image:helloworld-with-theme.png|400px]]
| + | |
- | | + | |
- | The screen is still a bit off (there are no borders around the main GtkLabel widget), but looks already better. The text is scaled to be more in sync with the other text sizes and also the color is in sync with the platform color (it is not gray anymore).
| + | |