\subchapter{Third party libraries and applications}{Objective: Learn
  how to leverage existing libraries and applications: how to
  configure, compile and install them}

To illustrate how to use existing libraries and applications, we will
extend the small root filesystem built in the {\em A tiny embedded
  system} lab to add the {\em DirectFB} graphic library and sample
applications using this library. Because many boards do not have a
display, we will test the result of this lab with {\em Qemu}.

We'll see that manually re-using existing libraries is quite tedious,
so that more automated procedures are necessary to make it
easier. However, learning how to perform these operations manually
will significantly help you when you'll face issues with more
automated tools.

\section{Figuring out library dependencies}

As most libraries, DirectFB depends on other libraries, and these
dependencies are different depending on the configuration chosen for
DirectFB. In our case, we will enable support for:

\begin{itemize}
\item PNG image loading
\item JPEG image loading
\item Font rendering using a font engine
\end{itemize}

The PNG image loading feature will be provided by the {\em libpng}
library, the JPEG image loading feature by the {\em jpeg} library and
the font engine will be implemented by the {\em FreeType} library. The
{\em libpng} library itself depends on the {\em zlib}
compression/decompression library. So, we end up with the following
dependency tree:

\begin{center}
\includegraphics[width=\textwidth]{labs/sysdev-thirdparty/directfb-dependencies.pdf}
\end{center}

Of course, all these libraries rely on the C library, which is not
mentioned here, because it is already part of the root filesystem
built in the {\em A tiny embedded system} lab. You might wonder how to
figure out this dependency tree by yourself. Basically, there are
several ways, that can be combined:

\begin{itemize}
\item Read the library documentation, which often mentions the
  dependencies;
\item Read the help message of the configure script (by running
  \code{./configure --help}).
\item By running the configure script, compiling and looking at the
  errors.
\end{itemize}

To configure, compile and install all the components of our system,
we're going to start from the bottom of the tree with {\em zlib}, then
continue with {\em libpng}, \emph{jpeg} and \emph{FreeType}, to
finally compile \emph{DirectFB} and the \emph{DirectFB} sample
applications.

\section{Preparation}

For our cross-compilation work, we will need to separate spaces:
\begin{itemize}
\item A \emph{staging} space in which we will directly install all the
  packages: non-stripped versions of the libraries, headers,
  documentation and other files needed for the compilation. This
  \emph{staging} space can be quite big, but will not be used on our
  target, only for compiling libraries or applications;
\item A \emph{target} space, in which we will copy only the required
  files from the \emph{staging} space: binaries and libraries, after
  stripping, configuration files needed at runtime, etc. This target
  space will take a lot less space than the \emph{staging} space, and
  it will contain only the files that are really needed to make the
  system work on the target.
\end{itemize}

To sum up, the {\em staging} space will contain everything that's
needed for compilation, while the {\em target} space will contain only
what's needed for execution.

So, in \code{/home/<user>/felabs/sysdev/thirdparty}, create two
directories: \code{staging} and \code{target}.

For the target, we need a basic system with BusyBox, device nodes and
initialization scripts. We will re-use the system built in the {\em A
  tiny embedded system} lab, so copy this system in the target
directory:

\begin{verbatim}
sudo cp -a /home/<user>/felabs/sysdev/tinysystem/nfsroot/* target/
\end{verbatim}

The copy must be done as \code{root}, because the root filesystem of
the {\em A tiny embedded system} lab contains a few device nodes.

\section{Testing}

Make sure the \code{target/} directory is exported by your NFS server
by adding the following line to \code{/etc/exports}:

\scriptsize
\begin{verbatim}
/home/<user>/felabs/sysdev/thirdparty/target 172.20.0.2(rw,no_root_squash,no_subtree_check)
\end{verbatim}
\normalsize

And restart your NFS server.

Install the Qemu emulator for non-x86 architectures by installing the
\code{qemu-kvm-extras} package.

Modify the \code{/etc/qemu-ifup} script so that it just contains 2 lines:
\begin{verbatim}
#!/bin/sh
/sbin/ifconfig $1 172.20.0.1
\end{verbatim}

Then, run Qemu with the provided script:

\begin{verbatim}
./run_qemu
\end{verbatim}

The system should boot and give you a prompt.

\section{zlib}

\code{Zlib} is a compression/decompression library available at
\url{http://www.zlib.net/}. Download version 1.2.5, and extract it in
\code{/home/<user>/felabs/sysdev/thirdparty/}.

By looking at the \code{configure} script, we see that this configure
script has not been generated by \code{autoconf} (otherwise it would
contain a sentence like {\em Generated by GNU Autoconf
  2.62}). Moreover, the project doesn't use automake since there are
no Makefile.am files. So zlib uses a custom build system, not a build
system based on the classical autotools.

Let's try to configure and build zlib:

\begin{verbatim}
./configure
make
\end{verbatim}

You can see that the files are getting compiled with gcc, which
generates code for x86 and not for the target platform. This is
obviously not what we want, so we tell the configure script to use the
ARM cross-compiler:

\begin{verbatim}
CC=arm-linux-gcc ./configure
\end{verbatim}

Of course, the \code{arm-linux-gcc} cross-compiler must be in your
PATH prior to running the configure script. The CC environment
variable is the classical name for specifying the compiler to
use. Moreover, the beginning of the configure script tells us about
this:

\begin{verbatim}
# To impose specific compiler or flags or
# install directory, use for example:
#    prefix=$HOME CC=cc CFLAGS="-O4" ./configure
\end{verbatim}

Now when you compile with make, the cross-compiler is used. Look at
the result of compiling: a set of object files, a file \code{libz.a}
and set of \code{libz.so*} files.

The \code{libz.a} file is the static version of the library. It has
been generated using the following command:

\begin{verbatim}
ar rc libz.a adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o \
      trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
\end{verbatim}

It can be used to compile applications linked statically with the zlib
library, as shown by the compilation of the example program:

\begin{verbatim}
arm-linux-gcc -O3 -DUSE_MMAP -o example example.o -L. libz.a
\end{verbatim}

In addition to this static library, there is also a dynamic version of
the library, the \code{libz.so*} files. The shared library itself is
\code{libz.so.1.2.5}, it has been generated by the following command
line:

\begin{verbatim}
arm-linux-gcc -shared -Wl,-soname,libz.so.1 -o libz.so.1.2.5 \
              adler32.o compress.o crc32.o gzio.o uncompr.o  \
              deflate.o trees.o zutil.o inflate.o infback.o  \
              inftrees.o inffast.o
\end{verbatim}

And creates symbolic links \code{libz.so} and \code{libz.so.1}:

\begin{verbatim}
ln -s libz.so.1.2.3 libz.so
ln -s libz.so.1.2.3 libz.so.1
\end{verbatim}

These symlinks are needed for two different reasons:

\begin{itemize}
\item \code{libz.so} is used at compile time when you want to compile
  an application that is dynamically linked against the library. To do
  so, you pass the \code{-lLIBNAME} option to the compiler, which will
  look for a file named \code{lib<LIBNAME>.so}. In our case, the
  compilation option is \code{-lz} and the name of the library file is
  \code{libz.so}. So, the \code{libz.so} symlink is needed at compile
  time;
\item \code{libz.so.1} is needed because it is the {\em SONAME} of the
  library. {\em SONAME} stands for {\em Shared Object Name}. It is the
  name of the library as it will be stored in applications linked
  against this library. It means that at runtime, the dynamic loader
  will look for exactly this name when looking for the shared
  library. So this symbolic link is needed at runtime.
\end{itemize}

To know what's the {\em SONAME} of a library, you can use:
\begin{verbatim}
arm-linux-readelf -d libz.so.1.2.5
\end{verbatim}

and look at the \code{(SONAME)} line. You'll also see that this
library needs the C library, because of the \code{(NEEDED)} line on
\code{libc.so.0}.

The mechanism of \code{SONAME} allows to change the library without
recompiling the applications linked with this library. Let's say that
a security problem is found in zlib 1.2.5, and fixed in the next
release 1.2.6. You can recompile the library, install it on your
target system, change the link \code{libz.so.1} so that it points to
\code{libz.so.1.2.6} and restart your applications. And it will work,
because your applications don't look specifically for
\code{libz.so.1.2.5} but for the {\em SONAME}
\code{libz.so.1}. However, it also means that as a library developer,
if you break the ABI of the library, you must change the {\em SONAME}:
change from \code{libz.so.1} to \code{libz.so.2}.

Finally, the last step is to tell the configure script where the
library is going to be installed. Most configure scripts consider that
the installation prefix is \code{/usr/local/} (so that the library is
installed in \code{/usr/local/lib}, the headers in
\code{/usr/local/include}, etc.). But in our system, we simply want
the libraries to be installed in the \code{/usr} prefix, so let's tell
the configure script about this:

\begin{verbatim}
CC=arm-linux-gcc ./configure --prefix=/usr
make
\end{verbatim}

For the zlib library, this option may not change anything to the
resulting binaries, but for safety, it is always recommended to make
sure that the prefix matches where your library will be running on the
target system.

Do not confuse the {\em prefix} (where the application or library will
be running on the target system) from the location where the
application or library will be installed on your host while building
the root filesystem. For example, zlib will be installed in
\code{/home/<user>/felabs/sysdev/thirdparty/target/usr/lib/} because
this is the directory where we are building the root filesystem, but
once our target system will be running, it will see zlib in
\code{/usr/lib}. The prefix corresponds to the path in the target
system and {\bf never} on the host. So, one should {\bf never} pass a
prefix like \code{/home/<user>/felabs/sysdev/thirdparty/target/usr},
otherwise at runtime, the application or library may look for files
inside this directory on the target system, which obviously doesn't
exist! By default, most build systems will install the application or
library in the given prefix (\code{/usr} or \code{/usr/local}), but
with most build systems (including {\em autotools}), the installation
prefix can be overriden, and be different from the configuration
prefix.

First, let's make the installation in the {\em staging} space:
\begin{verbatim}
make DESTDIR=../staging install
\end{verbatim}

Now look at what has been installed by zlib:
\begin{itemize}
\item A manpage in \code{/usr/share/man}
\item A pkgconfig file in \code{/usr/lib/pkgconfig}. We'll come back to these
  later
\item The shared and static versions of the library in \code{/usr/lib}
\item The headers in \code{/usr/include}
\end{itemize}

Finally, let's install the library in the {\em target} space:

\begin{enumerate}
\item Create the \code{target/usr/lib} directory, it will contain the
  stripped version of the library
\item Copy the dynamic version of the library. Only \code{libz.so.1} and \code{libz.so.1.2.5} are needed, since \code{libz.so.1} is the {\em SONAME} of the library and \code{libz.so.1.2.5} is the real binary:\\
  \code{cp -a libz.so.1* ../target/usr/lib}
\item Strip the library:\\
  \code{arm-linux-strip ../target/usr/lib/libz.so.1.2.5}
\end{enumerate}

Ok, we're done with zlib!

\section{Libpng}

Download libpng from its official website at
\url{http://www.libpng.org/pub/png/libpng.html}. We tested the lab
with version 1.4.3. Please stick to this version as newer versions are
incompatible with the DirectFB version we use in this lab.

Once uncompressed, we quickly discover that the libpng build system is
based on the {\em autotools}, so we will work with a regular configure
script.

As we've seen previously, if we just run \code{./configure}, the build
system will use the native compiler to build the library, which is not
what we want. So let's tell the build system to use the
cross-compiler:

\begin{verbatim}
CC=arm-linux-gcc ./configure
\end{verbatim}

Quickly, you should get an error saying:

\begin{verbatim}
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details.
If you look at config.log, you quickly understand what's going on:
configure:2942: checking for C compiler default output file name
configure:2964: arm-linux-gcc    conftest.c  >&5
configure:2968: $? = 0
configure:3006: result: a.out
configure:3023: checking whether the C compiler works
configure:3033: ./a.out
./configure: line 3035: ./a.out: cannot execute binary file
\end{verbatim}

The configure script compiles a binary with the cross-compiler and
then tries to run it on the development workstation. Obviously, it
cannot work, and the system says that it
\code{cannot execute binary file}. The job of the configure script is
to test the configuration of the system. To do so, it tries to compile
and run a few sample applications to test if this library is
available, if this compiler option is supported, etc. But in our case,
running the test examples is definitely not possible. We need to tell
the configure script that we are cross-compiling, and this can be done
using the \code{--build} and \code{--host} options, as described in
the help of the configure script:

\begin{verbatim}
System types:
  --build=BUILD	configure for building on BUILD [guessed]
  --host=HOST	cross-compile to build programs to run on HOST [BUILD]
\end{verbatim}

The \code{--build} option allows to specify on which system the
package is built, while the \code{--host} option allows to specify on
which system the package will run. By default, the value of the
\code{--build} option is guessed and the value of \code{--host} is the
same as the value of the \code{--build} option. The value is guessed
using the \code{./config.guess} script, which on your system should
return \code{i686-pc-linux-gnu}. See
\url{http://www.gnu.org/software/autoconf/manual/html_node/Specifying-Names.html}
for more details on these options.

So, let's override the value of the \code{--host} option:

\begin{verbatim}
CC=arm-linux-gcc ./configure --host=arm-linux
\end{verbatim}

Now, we go a little bit further in the execution of the configure
script, until we reach:

\begin{verbatim}
checking for zlibVersion in -lz... no
configure: error: zlib not installed
\end{verbatim}

Again, we can check in config.log what the configure script is trying
to do:

\footnotesize
\begin{verbatim}
configure:12452: checking for zlibVersion in -lz
configure:12487: arm-linux-gcc -o conftest -g -O2   conftest.c -lz  -lm  >&5
/usr/local/xtools/arm-unknown-linux-uclibcgnueabi/[...]usr/bin/[...]/ld: cannot find -lz
collect2: ld returned 1 exit status
\end{verbatim}
\normalsize

The configure script tries to compile an application against {\em
  zlib} (as can be seen from the \code{-lz} option): {\em libpng} uses
the {\em zlib} library, so the \code{configure} script wants to make
sure this library is already installed. Unfortunately, the \code{ld}
linker doesn't find this library. So, let's tell the linker where to
look for libraries using the \code{-L} option followed by the
directory where our libraries are (in \code{staging/usr/lib}). This
\code{-L} option can be passed to the linker by using the
\code{LDFLAGS} at configure time, as told by the help text of the
configure script:

\begin{verbatim}
  LDFLAGS       linker flags, e.g. -L<lib dir> if you have
                libraries in a nonstandard directory <lib dir>
\end{verbatim}

Let's use this \code{LDFLAGS} variable:

\begin{verbatim}
LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
CC=arm-linux-gcc \
./configure --host=arm-linux
\end{verbatim}

Let's also specify the prefix, so that the library is compiled to be
installed in \code{/usr} and not \code{/usr/local}:

\begin{verbatim}
 LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
 CC=arm-linux-gcc \
./configure --host=arm-linux --prefix=/usr
\end{verbatim}

Then, run the compilation using make. Quickly, you should get a pile
of error messages, starting with:

\begin{verbatim}
In file included from png.c:13:
png.h:470:18: error: zlib.h: No such file or directory
\end{verbatim}

Of course, since {\em libpng} uses the {\em zlib} library, it includes
its header file! So we need to tell the C compiler where the headers
can be found: there are not in the default directory
\code{/usr/include/}, but in the \code{/usr/include} directory of our
{\em staging} space. The help text of the configure script says:

\begin{verbatim}
  CPPFLAGS              C/C++/Objective C preprocessor flags,
                        e.g. -I<include dir> if you have headers
                        in a nonstandard directory <include dir>
\end{verbatim}

Let's use it:

\begin{verbatim}
LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
CPPFLAGS=-I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include \
CC=arm-linux-gcc \
./configure --host=arm-linux --prefix=/usr
\end{verbatim}

Then, run the compilation with make. Hopefully, it works!

Let's now begin the installation process.  Before really installing in
the staging directory, let's install in a dummy directory, to see
what's going to be installed (this dummy directory will not be used
afterwards, it is only to verify what will be installed before
polluting the staging space):

\begin{verbatim}
make DESTDIR=/tmp/libpng/ install
\end{verbatim}

The \code{DESTDIR} variable can be used with all Makefiles based on
automake. It allows to override the installation directory: instead of
being installed in the configuration-prefix, the files will be
installed in \code{DESTDIR/configuration-prefix}.

Now, let's see what has been installed in \code{/tmp/libpng/}:

\begin{verbatim}
./usr/lib/libpng.la                     -> libpng14.la
./usr/lib/libpng14.a
./usr/lib/libpng14.la
./usr/lib/libpng14.so                   -> libpng14.so.14.3.0
./usr/lib/libpng14.so.14                -> libpng14.so.14.3.0
./usr/lib/libpng14.so.14.3.0
./usr/lib/libpng.a                      -> libpng14.a
./usr/lib/libpng.la                     -> libpng14.la
./usr/lib/libpng.so                     -> libpng14.so
./usr/lib/pkgconfig/libpng.pc           -> libpng14.pc
./usr/lib/pkgconfig/libpng14.pc
./usr/share/man/man5/png.5
./usr/share/man/man3/libpngpf.3
./usr/share/man/man3/libpng.3
./usr/include/pngconf.h                 -> libpng14/pngconf.h
./usr/include/png.h                     -> libpng14/png.h
./usr/include/libpng14/pngconf.h
./usr/include/libpng14/png.h
./usr/bin/libpng-config                 -> libpng14-config
./usr/bin/libpng14-config
\end{verbatim}

So, we have:
\begin{itemize}

\item The library, with many symbolic links

  \begin{itemize}
  \item \code{libpng14.so.14.3.0}, the binary of the current version of
    library
  \item \code{libpng14.so.14}, a symbolic link to
    \code{libpng14.so.14.3.0}, so that applications using
    \code{libpng14.so.14} as the {\em SONAME} of the library will find
    nit and use the current version
  \item \code{libpng14.so} is a symbolic link to
    \code{libpng14.so.14.3.0}. So it points to the current version of
    the library, so that new applications linked with \code{-lpng14}
    will use the current version of the library \code{libpng.so} is a
    symbolic link to libpng14.so. So applications linked with
    \code{-lpng} will be linked with the current version of the
    library (and not the obsolete one since we don't want anymore to
    link applications against the obsolete version!)
  \item \code{libpng14.a} is a static version of the library
  \item \code{libpng.a} is a symbolic link to \code{libpng14.a}, so
    that applications statically linked with \code{libpng.a} will in
    fact use the current version of the library
  \item \code{libpng14.la} is a configuration file generated by {\em
      libtool} which gives configuration details for the library. It
    will be used to compile applications and libraries that rely on
    libpng.
  \item \code{libpng.la} is a symbolic link to \code{libpng14.la}: we
    want to use the current version for new applications, once again.
  \end{itemize}

\item The {\em pkg-config} files, in \code{/usr/lib/pkgconfig/}. These
  configuration files are used by the pkg-config tool that we will
  cover later. They describe how to link new applications against the
  library.

\item The manual pages in \code{/usr/share/man/}, explaining how to use the
  library.

\item The header files, in \code{/usr/include/}, needed to compile new
  applications or libraries against {\em libpng}. They define the
  interface to {\em libpng}. There are symbolic links so that one can
  choose between the following solutions:

  \begin{itemize}

  \item Use \code{#include <png.h>} in the source code and compile with
    the default compiler flags

  \item Use \code{#include <png.h>} in the source code and compile
    with \code{-I/usr/include/libpng14}

  \item Use \code{#include <libpng14/png.h>} in the source and compile
    with the default compiler flags

  \end{itemize}

\item The \code{/usr/bin/libpng14-config} tool and its symbolic link
  \code{/usr/bin/libpng-config}. This tool is a small shell script
  that gives configuration informations about the libraries, needed to
  know how to compile applications/libraries against libpng. This
  mechanism based on shell scripts is now being superseded by {\em
    pkg-config}, but as old applications or libraries may rely on it,
  it is kept for compatibility.

\end{itemize}

Now, let's make the installation in the {\em staging} space:

\begin{verbatim}
make DESTDIR=/home/<user>/felabs/sysdev/thirdparty/staging/ install
\end{verbatim}

Then, let's install only the necessary files in the {\em target}
space, manually:

\begin{verbatim}
cd ..
cp -a staging/usr/lib/libpng14.so.* target/usr/lib
arm-linux-strip target/usr/lib/libpng14.so.14.3.0
\end{verbatim}

And we're finally done with libpng!

\section{libjpeg}

Now, let's work on {\em libjpeg}. Download it from
\url{http://www.ijg.org/files/jpegsrc.v8.tar.gz} and extract it.

Configuring {\em libjpeg} is very similar to the configuration of the
previous libraries:

\begin{verbatim}
CC=arm-linux-gcc ./configure --host=arm-linux \
                             --prefix=/usr
\end{verbatim}

Of course, compile the library:

\begin{verbatim}
make
\end{verbatim}

Installation to the {\em staging} space can be done using the
classical \code{DESTDIR} mechanism:

\begin{verbatim}
make DESTDIR=/home/<user>/felabs/sysdev/thirdparty/staging/ install
\end{verbatim}

And finally, install manually the only needed files at runtime in the
{\em target} space:

\begin{verbatim}
cd ..
cp -a staging/usr/lib/libjpeg.so.8* target/usr/lib/
arm-linux-strip target/usr/lib/libjpeg.so.8.0.0
\end{verbatim}

Done with libjpeg!

\section{FreeType}

The {\em FreeType} library is the next step. Grab the tarball from
\url{http://www.freetype.org}. We tested the lab with version 2.4.2
but more other versions may also work. Uncompress the tarball.

The FreeType build system is a nice example of what can be done with a
good usage of the autotools. Cross-compiling FreeType is very
easy. First, the configure step:

\begin{verbatim}
CC=arm-linux-gcc ./configure --host=arm-linux  \
                             --prefix=/usr
\end{verbatim}

Then, compile the library:

\begin{verbatim}
make
\end{verbatim}

Install it in the {\em staging} space:

\begin{verbatim}
make DESTDIR=/home/<user>/felabs/sysdev/thirdparty/staging/ install
\end{verbatim}

And install only the required files in the {\em target} space:

\begin{verbatim}
cd ..
cp -a staging/usr/lib/libfreetype.so.6* target/usr/lib/
arm-linux-strip target/usr/lib/libfreetype.so.6.6.0
\end{verbatim}

Done with FreeType!

\section{DirectFB}

Finally, with {\em zlib}, {\em libpng}, {\em jpeg} and {\em FreeType},
all the dependencies of DirectFB are ready. We can now build the
DirectFB library itself. Download it from the official website, at
\url{http://www.directfb.org/}. We tested version 1.4.5 of the
library. As usual, extract the tarball.

Before configuring DirectFB, let's have a look at the available
options by running \code{./configure --help}. A lot of options are
available. We see that:

\begin{itemize}
\item Support for Fbdev (the Linux framebuffer) is automatically
  detected, so that's fine;
\item Support for PNG, JPEG and FreeType is enabled by default, so
  that's fine;
\item We should specify a value for \code{--with-gfxdrivers}. The
  hardware emulated by Qemu doesn't have any accelerated driver in
  DirectFB, so we'll pass \code{--with-gfxdrivers=none};
\item We should specify a value for \code{--with-inputdrivers}. We'll
  need keyboard (for the keyboard) and linuxinput to support the Linux
  Input subsystem. So we'll pass
  \code{--with-inputdrivers=keyboard,linuxinput}
\end{itemize}

So, let's begin with a configure line like:

\begin{verbatim}
CC=arm-linux-gcc ./configure --host=arm-linux \
        --prefix=/usr --with-gfxdrivers=none \
        --with-inputdrivers=keyboard,linuxinput
\end{verbatim}

In the output, we see:

\begin{verbatim}
*** JPEG library not found. JPEG image provider will not be built.
\end{verbatim}

So let's look in config.log for the JPEG issue. By search for
\code{jpeg}, you can find:

\footnotesize
\begin{verbatim}
configure:24701: arm-linux-gcc -o conftest [...] conftest.c -ljpeg  -ldl -lpthread  >&5
/usr/local/xtools/arm-unknown-linux-uclibcgnueabi/[...]/bin/ld: cannot find -ljpeg
\end{verbatim}
\normalsize

Of course, it cannot find the jpeg library, since we didn't pass the
proper \code{LDFLAGS} and \code{CFLAGS} telling where our libraries
are. So let's configure again with:

\small
\begin{verbatim}
LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
CPPFLAGS=-I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include \
CC=arm-linux-gcc \
./configure --host=arm-linux --prefix=/usr \
 --with-gfxdrivers=none --with-inputdrivers=keyboard,linuxinput
\end{verbatim}
\normalsize

Ok, now at the end of the configure, we get:

\begin{verbatim}
JPEG             yes  -ljpeg
PNG              yes  -I/usr/include/libpng12 -lpng12
[...]
FreeType2        yes  -I/usr/include/freetyp2 -lfreetype
\end{verbatim}

It found the JPEG library properly, but for libpng and freetype, it
has added \code{-I} options that points to the libpng and freetype libraries
installed on our host (x86) and not the one of the target. This is not
correct!

In fact, the DirectFB configure script uses the {\em pkg-config}
system to get the configuration parameters to link the library against
libpng and FreeType. By default, {\em pkg-config} looks in
\code{/usr/lib/pkgconfig/} for \code{.pc} files, and because the
\code{libfreetype6-dev} and \code{libpng12-dev} packages are already
installed in your system (it was installed in a previous lab as a
dependency of another package), then the configure script of DirectFB
found the libpng and FreeType libraries of your host!

This is one of the biggest issue with cross-compilation: mixing host
and target libraries, because build systems have a tendency to look
for libraries in the default paths. In our case, if
\code{libfreetype6-dev} was not installed, then the
\code{/usr/lib/pkgconfig/freetype2.pc} file wouldn't exist, and the
configure script of DirectFB would have said something like {\em
  Sorry, can't find FreeType}.

So, now, we must tell {\em pkg-config} to look inside the
\code{/usr/lib/pkgconfig/} directory of our {\em staging} space. This
is done through the \code{PKG_CONFIG_PATH} environment variable, as
explained in the manual page of \code{pkg-config}.

Moreover, the \code{.pc} files contain references to paths. For
example, in
\code{/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib/pkgconfig/freetype2.pc},
we can see:

\begin{verbatim}
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
[...]
Libs: -L${libdir} -lfreetype
Cflags: -I${includedir}/freetype2 -I${includedir}
\end{verbatim}

So we must tell \code{pkg-config} that these paths are not absolute,
but relative to our {\em staging} space. This can be done using the
\code{PKG_CONFIG_SYSROOT_DIR} environment variable.

Then, let's run the configuration of DirectFB again, passing the
\code{PKG_CONFIG_PATH} and \code{PKG_CONFIG_SYSROOT_DIR} environment
variables:

\small
\begin{verbatim}
LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
CPPFLAGS=-I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include \
PKG_CONFIG_PATH=/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib/pkgconfig \
PKG_CONFIG_SYSROOT_DIR=/home/<user>/felabs/sysdev/thirdparty/staging \
CC=arm-linux-gcc \
./configure --host=arm-linux --prefix=/usr \
 --with-gfxdrivers=none --with-inputdrivers=keyboard,linuxinput
\end{verbatim}
\normalsize

Ok, now, the lines related to Libpng and FreeType 2 looks much better:

\footnotesize
\begin{verbatim}
PNG       yes -I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include/libpng14 -lpng14
FreeType2 yes -I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include/freetype2 -lfreetype
\end{verbatim}
\normalsize

Let's build DirectFB with make. After a while, it fails, complaining
that \code{X11/Xlib.h} and other related header files cannot be
found. In fact, if you look back the the \code{./configure} script
output, you can see:

\begin{verbatim}
X11 support		yes		-lX11 -lXext
\end{verbatim}

Because X11 was installed on our host, DirectFB \code{./configure}
script thought that it should enable support for it. But we won't have
X11 on our system, so we have to disable it explicitly. In the
\code{./configure --help} output, one can see:

\begin{verbatim}
--enable-x11		build with X11 support [default=auto]
\end{verbatim}

So we have to run the configuration again with the same arguments, and
add \code{--disable-x11} to them.

The build now goes further, but still fails with another error:

\begin{verbatim}
/usr/lib/libfreetype.so: could not read symbols: File in wrong format
\end{verbatim}

As you can read from the above command line, the Makefile is trying to
feed an x86 binary (\code{/usr/lib/libfreetype.so}) to your ARM
toolchain. Instead, it should have been using
\code{usr/lib/libfreetype.so} found in your staging environment.

This happens because the {\em libtool} \code{.la} files in your
staging area need to be fixed to describe the right paths in this
staging area. So, in the .la files, replace \code{libdir='/usr/lib'}
by
\code{libdir='/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib'}. Restart
the build again, preferably from scratch (\code{make clean} then
\code{make}) to be sure everything is fine.

Finally, it builds!

Now, install DirectFB to the {\em staging} space using:

\begin{verbatim}
make DESTDIR=/home/<user>/felabs/sysdev/thirdparty/staging/ install
\end{verbatim}

And so the installation in the {\em target} space:

\begin{itemize}

\item First, the libraries:
\small
\begin{verbatim}
cd ..
cp -a staging/usr/lib/libdirect-1.4.so.5* target/usr/lib
cp -a staging/usr/lib/libdirectfb-1.4.so.5* target/usr/lib
cp -a staging/usr/lib/libfusion-1.4.so.5* target/usr/lib
arm-linux-strip target/usr/lib/libdirect-1.4.so.5.0.0
arm-linux-strip target/usr/lib/libdirectfb-1.4.so.5.0.0
arm-linux-strip target/usr/lib/libfusion-1.4.so.5.0.0
\end{verbatim}
\normalsize

\item Then, the plugins that are dynamically loaded by DirectFB. We
  first copy the whole \code{/usr/lib/directfb-1.4-5/} directory, then
  remove the useless files (\code{.la}) and finally strip the
  \code{.so} files:

\small
\begin{verbatim}
cp -a staging/usr/lib/directfb-1.4-5/ target/usr/lib
find target/usr/lib/directfb-1.4-5/ -name '*.la' -exec rm {} \;
find target/usr/lib/directfb-1.4-5/ -name '*.so' -exec arm-linux-strip {} \;
\end{verbatim}
\normalsize

\end{itemize}

\section{DirectFB examples}

To test that our DirectFB installation works, we will use the example
applications provided by the DirectFB project. Start by downloading
the tarball at
\url{http://www.directfb.org/downloads/Extras/DirectFB-examples-1.2.0.tar.gz}
and extract it.

Then, we configure it just as we configured DirectFB:

\small
\begin{verbatim}
LDFLAGS=-L/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib \
CPPFLAGS=-I/home/<user>/felabs/sysdev/thirdparty/staging/usr/include \
PKG_CONFIG_PATH=/home/<user>/felabs/sysdev/thirdparty/staging/usr/lib/pkgconfig \
PKG_CONFIG_SYSROOT_DIR=/home/<user>/felabs/sysdev/thirdparty/staging \
CC=arm-linux-gcc \
./configure --host=arm-linux --prefix=/usr
\end{verbatim}
\normalsize

Then, compile it with \code{make}. Soon a compilation error will occur
because \code{bzero} is not defined. The \code{bzero} function is a deprecated
BSD function, and \code{memset} should be used instead. The GNU C library
still defines \code{bzero}, but by default, the uClibc library doesn't
provide \code{bzero} (to save space). So, let's modify the source code in
\code{src/df_knuckles/matrix.c} to change the line:

\begin{verbatim}
#define M_CLEAR(m) bzero(m, MATRIX_SIZE)
\end{verbatim}

to

\begin{verbatim}
#define M_CLEAR(m) memset(m, 0, MATRIX_SIZE)
\end{verbatim}

Run the compilation again, it should succeed.

For the installation, as DirectFB examples are only applications and
not libraries, we don't really need them in the {\em staging} space,
but only in the {\em target} space. So we'll directly install in the
{\em target} space using the \code{install-strip} make target. This
make target is usually available with autotools based build
systems. In addition to the destination directory (\code{DESTDIR}
variable), we must also tell which strip program should be used, since
stripping is an architecture-dependent operation (\code{STRIP}
variable):

\begin{verbatim}
make STRIP=arm-linux-strip \
     DESTDIR=/home/<user>/felabs/sysdev/thirdparty/target/ install-strip
\end{verbatim}

\section{Final setup}

Start the system in Qemu using the \code{run_qemu} script, and try to
run the \code{df_andi} program, which is one of the DirectFB examples.

The application will fail to run, because the {\em pthread} library
(which is a component of the C library) is missing. This library is
available inside the toolchain. So let's add it to the target:

\begin{verbatim}
TOOLCHAIN_SYSROOT=$(arm-linux-gcc -print-sysroot)
cp -a $TOOLCHAIN_SYSROOT/lib/libpthread* target/lib/
\end{verbatim}

Then, try to run \code{df_andi} again. It will complain about
\code{libdl}, which is used to dynamically load libraries during
application execution. So let's add this library to the target:

\begin{verbatim}
cp -a $TOOLCHAIN_SYSROOT/lib/libdl* target/lib
\end{verbatim}

When running \code{df_andi} again, it will complain about
\code{libgcc_s}, so let's copy this library to the target:

\begin{verbatim}
cp -a $TOOLCHAIN_SYSROOT/lib/libgcc_s* target/lib
\end{verbatim}

Now, the application should no longer complain about missing
libraries. But when started, it should complain about the \code{/dev/fb0}
device file that doesn't exist. So let's create this device file:

\begin{verbatim}
sudo mknod target/dev/fb0 c 29 0
\end{verbatim}

Next executing the application will complain about missing
\code{/dev/ttyx} device files, so let's create them:

\begin{verbatim}
sudo mknod target/dev/tty0 c 4 0
sudo mknod target/dev/tty5 c 4 5
\end{verbatim}

Finally, when running \code{df_andi}, another error message shows up:

\small
\begin{verbatim}
Unable to dlopen '/usr/lib/[...]/libidirectfbimageprovider_png.so' !
	File not found
\end{verbatim}
\normalsize

DirectFB is trying to load the PNG plugin using the \code{dlopen()} function,
which is part of the \code{libdl} library we added to the target system
before. Unfortunately, loading the plugin fails with the {\em File not
found} error. However, the plugin is properly present, so the problem
is not the plugin itself. What happens is that the plugin depends on
the {\em libpng} library, which itself depends on the {\em mathematic}
library. And the mathematic library \code{libm} (part of the C library) has
not yet been added to our system. So let's do it:

\begin{verbatim}
cp -a $TOOLCHAIN_SYSROOT/lib/libm* target/lib
\end{verbatim}

Now, you can try and run the \code{df_andi} application!
