Tux
Communication
Mailing lists
Documentation
User Manual
Target board info.
Target chip info.
Support
Linux support
Bugzilla
Downloads
STLinux
Updates
Search
Google


The web
stlinux.com
Getting Started
Cross compiling GTK+ v2
ST Logo
Previous   Contents   Next
One Script to rule them all, One Script to find them, One Script to bring them all and in the Darkness bind them.

Background

This paper documents the efforts needed to cross compile the GTK+ v2 set of libraries on a Linux/Intel host for a SuperH based Linux target.

I have been developing and packaging applications for the STMicroelectronics Embedded Linux distribution for the SuperH family of microprocessors (STLinux) since 2000 and working on Linux and embedded systems in general since 1997.

STMicroelectronics is actively developing a port of Linux on the SuperH family of processor. Its contribution is available as a complete Embedded Linux distribution on www.linuxsh.st.com

GTK+ v2 (GTK2) is only one of the X11 widget libraries available in our distribution, the others being Qt/Embedded by Trolltech and the previous version of GTK+: version 1.2

GTK2 is more than a simple collection of widgets for X11. The whole system is comprised of four libraries: Glib, Atk, Pango and Gtk. Gtk itself is made of sub-libraries that cover the specific areas needed to draw a complex GUI on screen: gdk contains the low-level drawing routines, gdk-pixbuf handles all the standard image formats (Jpeg, PNG, GIF, etc.), and gtk implements the high-level visible widgets.

The decision to package a complex set of libraries like those that make GTK2 has been taken because of customer request. We knew in advance that packaging such a complex system was going to be difficult because of the intricate dependencies that such packages always show, dependencies that become even more difficult to get right when cross compiling in an environment different from the one where the library will actually be used.

The STMicroelectronics Embedded Linux Distribution

Our embedded Linux distribution, STLinux, is a collection of tools and applications created to support the development of Embedded Linux systems targeted at the SuperH family of processor on an host platform, currently an x86 PC running RedHat Linux.

It must be stressed that STLinux is not a complete distribution; it can only be installed on top of an already existing RedHat Linux system. All its packages have names starting with the stm- prefix to clearly separate them from the standard packages installed on the host.

STLinux is completely self contained in a single directory rooted at /opt/STM/ST40Linux-1.0; from now on we'll call this directory $STROOT. The most important tools available are a cross compiler (gcc), a debugger with remote debugging capabilities (gdb), loaders for different evaluation boards, and a set of kernels with different configurations.

A set of packages (the stm-target-* ones) can be used to build a compact but fully functional target environment rooted at $STROOT/devkit/sh4/target. This environment provides a complete root filesystem that can be used on the evaluation boards to create a working Linux system. It could be directly mounted using NFS or its content can be copied to a bootable flash memory.

The most important subtrees available in our distribution are, for our purpose, and relative to the base path shown above:

  • .../host
  • .../devkit/sh4
  • .../devkit/sh4/target

Each of these contains a fairly standard Linux tree of directories: /bin, /lib, /share and so on.

Let's look in more detail at the type of files contained in those directories

/host
This tree contains files that may be needed when developing an application for STLinux on the host machine. Binaries in the bin subdirectory have a target- prefix, e.g. target-shellconfig. Typically the equivalent SH version is installed somewhere in $STROOT/devkit/sh4/target. These files are located here because they are considered architecture independent, i.e. they are the same regardless whether you are using an SH3 or SH4 target.
/devkit/sh4
This directory contains x86 hosted development tools that are in some way dependent on the target architecture. Binaries in the bin subdirectory have a sh4-linux- prefix, e.g. sh4-linux-gcc. The directory also contains header and config files for SH libraries installed in the target subtree to be used when cross compiling on the host. These include the libtool .la files and the pkgconfig .pc files.
/devkit/sh4/target
This tree is a complete root filesystem for an SH4 target. It is populated by the stm-sh4-* rpm packages and can be mounted by a development board using NFS.

The reason why we focus on cross compilation is that many embedded Linux systems are not powerful enough to support a self-hosted complete development environment. This environment must nonetheless be available to leave to the developer the option of compiling complex packages on a target system. The computing power gained by developing on the host machine is balanced by the more complex environment needed by cross compilation.

The key issue in this setup is that libraries assume a "split-personality". The library itself, the header files, the libtool and pkg-config files, and any other files that may be related to a library, need to be usable in two very different environments: cross compiling on the host and also compiling or running an application on the target.

Every STLinux library package contains only the basic libraries needed to run applications on the target, while the -dev packages contain all the remaining files needed for development. This are the packages that provide the dual environment previously described.

Another key point that we tried to enforce in creating packages for the STLinux distribution is the independence from the host platform. Our distribution currently support RedHat 6.2 and 7.x.

Differences in the host environment should not affect a closed system like ours but they can become important when rebuilding the packages. This is due to the autoconf tools that tend to look for the information they need in many places and are difficult to constrain to a subset of the directory tree. They often end up looking for commands or libraries on the host system making the host environment an important factor in the whole process of cross-compiling packages.

The main STLinux developer tools all have their name prefixed with the sh4-linux string. Thus the SH4 compiler is named sh4-linux-gcc and so on. These tools are built and set up so that they look for and use libraries and header files only in the $STROOT directory.

If we cross compile a simple Hello World program hello.c using the -v option, we get the following output (slightly edited for readability):

...
/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3/cc1 -lang-c -v
-D__GNUC__=3 -D__GNUC_MINOR__=0 -D__GNUC_PATCHLEVEL__=3 -D__ELF__ -Dunix -D__sh__
-Dlinux -D__ELF__ -D__unix__ -D__sh__ -D__linux__ -D__unix -D__linux -Asystem=posix
-D__NO_INLINE__ -D__STDC_HOSTED__=1 -D__LITTLE_ENDIAN__ -D__SH4__ hello.c
-musermode -ml -m4 -quiet -dumpbase hello.c -version -o /tmp/ccJ2qMEH.s
GNU CPP version 3.0.3 (STMicroelectronics/Linux Basic) (cpplib) (SH4 GNU/Linux with ELF)
GNU C version 3.0.3 (STMicroelectronics/Linux Basic) (sh4-linux)
    compiled by GNU C version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release).
#include "..." search starts here:
#include <...> search starts here:
/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3/include
/opt/STM/ST40Linux-1.0/devkit/sh4/target/usr/include
End of search list.
...
/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3/collect2
-dynamic-linker /lib/ld-linux.so.2
/opt/STM/ST40Linux-1.0/devkit/sh4/target/usr/lib/crt1.o
/opt/STM/ST40Linux-1.0/devkit/sh4/target/usr/lib/crti.o
/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3/crtbegin.o
-L/opt/STM/ST40Linux-1.0/devkit/sh4/target/lib
-L/opt/STM/ST40Linux-1.0/devkit/sh4/target/usr/lib
-L/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3
-L/opt/STM/ST40Linux-1.0/devkit/sh4/sh4-linux/lib
/tmp/ccsYYbUi.o -lgcc -lc -lgcc
/opt/STM/ST40Linux-1.0/devkit/sh4/lib/gcc-lib/sh4-linux/3.0.3/crtend.o
/opt/STM/ST40Linux-1.0/devkit/sh4/target/usr/lib/crtn.o

It is clear the all the tools work inside a self-contained environment rooted at $STROOT.

The Real Thing

The GTK+ v2 framework

The GTK2 system is more than a simple widget set. Is is a set of tightly connected libraries, each one optimized for a particular task, designed to build complex user interfaces for multi-lingual applications.

These libraries are distributed as separate packages and must be built following an exact sequence. Some of these libraries depends, in turn, on other software that should be already available in the system. Here is a brief description of the libraries from the www.gtk.org website.

GLib
This is the low-level core library that forms the basis of GTK+ and GNOME. It provides data structure handling for C, portability wrappers, and interfaces for such runtime functionality as an event loop, threads, dynamic loading, and an object system.
Pango
is a library for layout and rendering of text, with an emphasis on internationalization. It forms the core of text and font handling for GTK+-2.0.
ATK
The ATK library provides a set of interfaces for accessibility. By supporting the ATK interfaces, an application or toolkit can be used with such tools as screen readers, magnifiers, and alternative input devices.
GTK+
is a multi-platform toolkit for creating graphical user interfaces. Offering a complete set of widgets, GTK+ is suitable for projects ranging from small one-off projects to complete application suites.

The external dependencies of these four libraries are:

Freetype
This is the de-facto standard for the rendering of TrueType fonts and is used Pango and ?????
Graphics libraries (jpeg, png, tiff)
These are used to support image formats and are used by components inside GTK+

These libraries are considered available in their native (x86) versions on the build machine. While libjpeg, libpng and libtiff are quite stable and suitable versions are available on RedHat 6.x, Freetype can be more problematic. To build GTK2, Freetype 2 is in fact needed on the host.

Freetype

The first library built was Freetype. I knew it was a prerequisite for Pango and it is needed by other applications too.

Its build system uses autoconf but does it in a special way. Instead of being directly invoked before make, the configure script is called by a pre-existing Makefile using the setup target. Options for the script can be passed in using the CFG make variable. E.g.

make setup CFG="--prefix=/usr --build=i686-pc-linux-gnu --host=sh4-linux" CC="sh4-linux-gcc"

The content of the variable is used as the only command line arguments to configure.

The only important patch needed introduced the DESTDIR variable in builds/unix/install.mk as a prefix to all the destination directories to simplify the installation step.

As usual, at the end of the compilation, the host libtool files (.la) and the freetype-config utility had to be modified for a cross development environment.

Installation was straightforward with a simple

make install DESTDIR="%{buildroot}%{_stm_cross_target_dir}"

command. The host environment for cross compilation had to be created manually but this has became a standard procedure in our spec files.

GLib 2 for the host

This package provides a stripped down x86 version of GLib 2 and some of the binaries that come with it. Host versions of these tools are needed during the cross compilation phase and when building other packages. It must be noted that the need for this package emerged only after trying to compile GLib 2 for the target system. This added to the final time needed.

We decided to provide this package because we can't assume that a suitable version of glib2 is available on the host system (e.g. RedHat 6.x) and to be able to track changes in the library independently from the host distribution.

Building the library for the host system is easy. The only thing I had to do is passing configure the proper options to make the library aware of the unusual installation path ($STROOT/host.)

Installation was straightforward due to the DESTDIR and transform make variables. The first quirk in the system is found here: the transform variable is used to specify a sed command that is applied to the executables name. E.g.

transform="s,^,target-,"

This will prepend the string "target-" to the name of all executables. This modification is performed at install time but the pkg-config files are generated at the end of the configuration phase and therefore they still contain the original name. A sed command is used to fix this in the %install section of the spec file.

The commands installed by this package are:

  • $STROOT/host/bin/target-glib-genmarshal
  • $STROOT/host/bin/target-glib-gettextize
  • $STROOT/host/bin/target-glib-mkenums
  • $STROOT/host/bin/target-gobject-query

A brief note on the target-gobject-query command. It is supposed to DO WHAT WITH MODULES??? but will it work when handling modules for a different architecture?

GLib 2 for the target

This package marked the beginning of the complex stuff

The first thing you want to try after reading a bit about autoconf is the following simple command:

./configure --build="i686-pc-linux-gnu" --host="sh4-linux"

You get the following error message:

checking for extra flags to get ANSI library prototypes...
configure: error: cannot run test program while cross compiling

A bit of investigation shows that this is due to the following section of the configure.in:

dnl DU4 native cc currently needs -std1 for ANSI mode (instead of K&R)
AC_MSG_CHECKING([for extra flags to get ANSI library prototypes])
glib_save_LIBS=$LIBS
LIBS="$LIBS -lm"
AC_TRY_RUN([#include <math.h>
...

This is just the first example of the use of the AC_TRY_RUN() macro in autoconf scripts. Using this macro prevents the package to be configured (and built) in a cross development environment. A quick check shows 18 (eighteen) invocations of that macro in configure.in.

Many of those invocations can be avoided preloading the cache file config.cache with correct values. When configure runs it checks for this file and if found it sources it. config.cache is just a sequence of Bourne shell variable assignments. Many of the autoconf macros do not perform their checks if a certain variable is pre-defined. By preloading the cache with values we force configure to skip those tests and we avoid the problem. Yes, I know, it's ugly :-)

Here's how we do it (first few lines from the spec file):

# preload config.cache with proper values
cat > config.cache << EOF
glib_cv_long_long_format=\${glib_cv_long_long_format=ll}
glib_cv_stack_grows=\${glib_cv_stack_grows=no}
glib_cv_has__inline=\${glib_cv_has__inline=yes}
glib_cv_has__inline__=\${glib_cv_has__inline__=yes}
...

And we then invoke configure with the --cache-file="config.cache" option. 19 variables are needed to reach a successful completion of the configure script.

Some other problematic tests that use AC_TRY_RUN() without the possibility of being overridden with a cache variable are the threads and the poll() support sections. In order to fix these problems I had to patch configure.in and generate a new configure script. MORE DETAIL FROM THE PATCH

Even rebuilding configure can be problematic because the configure.in file requires autoconf 2.52 or higher while RedHat 7.3 still uses autoconf 2.13 as default. Version 2.52 is available but its name is autoconf-2.52. Using this filename in the spec file will make them non portable and will break when autoconf is upgraded.

After these modifications autoconf works and generate a working Makefile:

./configure --build="i686-pc-linux-gnu" --host="sh4-linux" --prefix="/usr" ...

Installation is again problematic because the standard libtool script tries to relink (what does it mean and why is it needed?) the libraries and fails with the following error:

$ make install DESTDIR="/tmp/testdir"

... lot of output ...

/bin/sh ../libtool  --mode=install /usr/bin/install -c libgobject-2.0.la \
	/tmp/testdir/usr/lib/libgobject-2.0.la
libtool: install: warning: relinking `libgobject-2.0.la'
( cd /home/chinstrap/users/acister/work/packages/BUILD/glib-2.0.4/gobject;
/bin/sh ../libtool --mode=relink sh4-linux-gcc -O2 -Wall -D_REENTRANT -o libgobject-2.0.la \
                   -rpath /usr/lib -version-info 0:4:0 -export-dynamic \
		   gboxed.lo ... object files ... gvaluetypes.lo \
		   ../glib/libglib-2.0.la -inst-prefix-dir /tmp/testdir
)
sh4-linux-gcc -shared  gboxed.lo ... object files ... gvaluetypes.lo \
            -L/usr/lib -L/tmp/testdir/usr/lib -lglib-2.0  -Wl,-soname -Wl,libgobject-2.0.so.0 \
	    -o .libs/libgobject-2.0.so.0.0.4
/usr/lib/libglib-2.0.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
libtool: install: error: relink `libgobject-2.0.la' with the above command before installing it
make[2]: *** [install-libLTLIBRARIES] Error 1
...

It is clear that libtool tries to link the SH4 object files with an x86 library located in /usr/lib. This is the result of some hard-coded paths in the libtool script itself.

Given the complexity of libtool this problem has been solved by using an extremely simple replacement called libtool-local that handles the installation phase with less "cleverness" and just installs things where they should go. The script is added to the top-level directory by the %prep section of the spec file.

The final command line for installation is then:

make install DESTDIR="/tmp/testdir" LIBTOOL="$(pwd)/libtool-local"

As usual the host libtool files (.la) and the pkg-config files (.pc) had to be rebuilt and the target specific directory tree had to be populated for a cross development environment. The files installed are needed when cross compiling SH4 applications that use GLib 2.

Atk for the target

This was easier. The only case where the autoconf system actually worked once provided the right environment and the right options.

As usual the host libtool files (.la) and the pkg-config files (.pc) had to be rebuilt and the target specific directory tree had to be populated for a cross development environment.

Pango for the host

The reason we need an host package for Pango is the pango-querymodules command. Is is used by the Makfiles of other libraries and is part of the standard development environment for Pango applications.

For the first attempt I configured the package as follows:

CFLAGS="-O2" ./configure --with-qt=no --disable-shared --with-included-modules=basic-ft2,basic-x

This works OK but leaves me with an executable with lots of dependancies on libraries that may not be available on the host:

$ ldd ./pango/pango-querymodules
libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0x40020000)
libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0x4005a000)
libdl.so.2 => /lib/libdl.so.2 (0x4005e000)
libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x40061000)
libXft.so.1 => /usr/X11R6/lib/libXft.so.1 (0x400c6000)
libXrender.so.1 => /usr/X11R6/lib/libXrender.so.1 (0x400f0000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x400f5000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40103000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x401d8000)
libc.so.6 => /lib/i686/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
$

Wich is a big number of libraries for a simple, command-line program that doesn't need half of them.

In the end I decided to go with a custom build sequence because I wanted a very simple pango library; the bare minimum needed to build pango-querymodules that, by itself, doesn't need X11 or Freetype, but only some pango functions and GLib 2.

The config file config.h and the list of files needed for this minimal libpango have been taken from a standard build run. The executable is basically built and installed by hand and only depends on the host GLib 2 library and glibc.

Pango for the target

At this point things are starting to get really difficult. First of all Pango needed a number of patches to work:

  • The glib-mkenums program name is hard-coded in Makefiles.am. Why? The macro @GLIB_MKENUMS@ is available for substitution in configure and could be used to override the custom setting by setting the environment variable with the same name.
  • The configure script tries to build the OpenType tests but it fails on RedHat 6.x. I had to delete the corresponding macro from configure.in and rebuild it.
  • Examples and tests are built by default but they fail when cross-compiling. The system tries to run the freshly built pango-querymodules command but it is an SH4 executable.
  • The pango-querymodules command name, needed during compilation, is hard-coded in the Makefiles to the one that has just been built (i.e. an SH4 executable). To make this work when cross compiling I patched the Makefiles and added a $TARGET_PREFIX variable to the command name. I still have to manually copy the x86 executable in the pango directory for this to work.

Having changed configure.in we have to rerun autoconf. This operation on Pango resulted in a number of problems.

  • On systems where GLib 2 is not available as part of the standard installation (e.g. RedHat 6.2) we get this error:
    error: no macro AM_PATH_GLIB_2_0
    
    This happens even if we have already installed the stm-host-glib2 package that provides a GLib 2 host development environment.
  • It seems that old versions of autoconf/automake/aclocal are required on the host computer. At least if we have to use automake. This is in contrast with other libraries that require autoconf >= 2.52 for example.
  • After running autoconf it seems that we need to run configure at least once on the host system in order to have a working environment. This makes Freetype 2 a needed package on the host machine. Another unneeded dependency.

Let's look at these in more detail.

The AM_PATH_GLIB_2_0 macro is used in configure.in and can be found in the glib-2.0.m4 file that is installed with glib2. On those systems where glib2 is not available as part of the standard installation (e.g. RedHat 6.2) the file is installed with the glib2-host-dev package outside of the canonical /usr/share/aclocal directory. (I.e. in $STROOT/host/share/aclocal)

When rebuilding the aclocal.m4 file in the pango top-level directory using the aclocal command, we could use the --acdir command line option to tell aclocal to search in $STROOT/host/share/aclocal but this doesn't work because many standard macros are missing now. The fact is that aclocal only looks in one directory for its m4 macro files: the default one (/usr/share/aclocal) or the one passed with the last --acdir option. If you have macros in more than one place you're stuck.

I solved this problem by copying at build time all the available m4 macros into one temporary directory and using this directory as argument to the --acdir option of aclocal. An interesting problem I run into while doing this is trying to locate the directories holding the m4 files. The --print-ac-dir option is not enough because it only prints /usr/share/aclocal (at least on 1.4-p5 and 1.5) and not the complete versioned directory /usr/share/aclocal-x.x.

This directory could be accessed knowing the aclocal version number but the strings printed using --version can have strange formats like 1.4-p5 or 1.5 or 1.6.1. After some cut and sed acrobatics I managed to extract the real version number in its X.X format and access the right versioned directory. A more uniform and easily machine readble version number would definitely help in this case.

The autoconf/automake/aclocal version mismatch was discovered because using automake 1.5 on a RedHat 7.3 box the reconfiguration step failed with cryptic messages. I had to revert back to the old versions (autoconf 2.13 and automake 1.4) for the process to work again. This is in contrast with the GLib 2 package where autoconf >= 2.52 was needed. These tools are already overly complex, a standardisation of the version used would help a lot.

If we had run configure and make in cross compile mode now, we would end up with two invocations of configure, the second one being triggered by a rule in the Makefiles when running make. To avoid configure being executed without the right options, I had to perform the following steps:

  1. Rebuild configure using automake -a -c and autoconf.
  2. Run configure with extremely simple options (this needs Freetype 2 on the host to succeed.)
  3. Run make distclean to trigger another automatic configure invocation and to clean the environment.
  4. Finally run configure in cross compile mode
  5. Run make defining the appopriate TARGET_PREFIX and ACLOCAL variables.

Installation is again tricky. I had to use the libtool-local script again because of re-linking problems. The target .la and .pc files are broken: they contain the host directory instead of /usr/lib; they had to be corrected with sed.

As usual the host libtool files (.la) and the pkg-config files (.pc) had to be rebuilt and the target specific directory tree had to be populated for a cross development environment.

The end of the installation phase should generate a pango.modules configuration file in /etc and this is problematic because the modules are SH4 binaries and the Intel version of pango-querymodules may have problems with them or generate wrong data. Some more info on this file would be appreciated. When is it needed? If only at runtime then it's OK to install it only in /devkit/sh4/target/etc while if it is needed at compile time as well, then it must be installed somewhere else too (probably with paths changed).

GTK2 for the host

We need this package because of two utilities that are needed while building the SH version: gtk-query-immodules-2.0 and gdk-pixbuf-csource.

Building a standard version of GTK2 for the host (i386) would also need all its dependencies (Glib, Freetype, Pango and maybe Atk) for the same host. Therefore I decided to compile the minimum amount of code needed to link those applications. In the end the files needed are just a few and a standard installation would have been a waste of resources.

The best example of this is the gtk-query-immodules-2.0 command that because of a single generic function (pango_split_file_list()) located in the pango library, would then need the whole library leading to the usual chain of dependencies for just a single function.

I solved this problem by importing from Pango the source file containing the function (pango_utils.c) using a patch file and modifying some GTK files to satisfy the needs of that function. The gtk-query-immodules-2.0 command is then build using a single gcc invocation and without any dependency apart from Glib.

To build gdk-pixbuf-csource we first need the gdk-pixbuf library and the image loaders needed by it. Again we do this manually because the standard makefile pulls in many unneeded libraries as dependencies of gdk-pixbuf.

GTK2 for the target

This is the main library. We have worked hard to get to this one.

This was so messy that in the end the only option available was to rewrite from scratch the build system.

I started trying to run configure in cross compilation mode. After setting the following environment variables

export    PKG_CONFIG_PATH="/opt/STM/ST40Linux-1.0/devkit/sh4/lib/pkgconfig"
export    FREETYPE_CONFIG="/opt/STM/ST40Linux-1.0/devkit/sh4/bin/sh4-linux-freetype-config"
export GDK_PIXBUF_CSOURCE="/opt/STM/ST40Linux-1.0/host/bin/target-gdk-pixbuf-csource"
export       GLIB_MKENUMS="/opt/STM/ST40Linux-1.0/host/bin/target-glib-mkenums"
export    GLIB_GENMARSHAL="/opt/STM/ST40Linux-1.0/host/bin/target-glib-genmarshal"
export      GOBJECT_QUERY="/opt/STM/ST40Linux-1.0/host/bin/target-gobject-query"

I could run configure:

./configure --host="%{_stm_target_config}" --build="%{_stm_host_config}" \
	--prefix="%{_stm_target_prefix}" --exec-prefix="%{_stm_target_exec_prefix}" \
	--sysconfdir="%{_stm_target_sysconf_dir}" --localstatedir="%{_stm_target_localstate_dir}" \
	--sharedstatedir="%{_stm_target_sharedstate_dir}" --mandir="%{_stm_target_man_dir}" \
	--infodir="%{_stm_target_info_dir}" --cache-file="config.cache" \
	--disable-gtk-doc --disable-glibtest --enable-debug="minimum" \
	--with-gdktarget="x11" --x-libraries="%{_stm_cross_x_dir}/lib" \
	--x-includes="%{_stm_cross_x_dir}/include"

Typing make now doesn't work. Again because of libtool and the absolute paths embedded in its code. While building the jpeg loader I got this error:

... lots of output ...

/bin/sh ../libtool --mode=link sh4-linux-gcc -O2 -Wall -o libpixbufloader-jpeg.la \
	-rpath /usr/lib/gtk-2.0/2.0.0/loaders \
	-avoid-version -module io-jpeg.lo -ljpeg libgdk_pixbuf-2.0.la -Wl,--export-dynamic \
	-L/opt/STM/ST40Linux-1.0/devkit/sh4/lib -lgmodule-2.0 -ldl -lgobject-2.0 -lglib-2.0 -lm
rm -fr .libs/libpixbufloader-jpeg.la .libs/libpixbufloader-jpeg.* .libs/libpixbufloader-jpeg.*
(cd . && ln -s io-jpeg.lo io-jpeg.o)
sh4-linux-gcc -shared  io-jpeg.lo \
	-Wl,--rpath -Wl,/home/chinstrap/users/acister/work/packages/BUILD/gtk+-2.0.5/gdk-pixbuf/.libs \
	-Wl,--rpath -Wl,/opt/STM/ST40Linux-1.0/devkit/sh4/lib \
	-Wl,--rpath -Wl,/opt/STM/ST40Linux-1.0/devkit/sh4/lib \
	-L/opt/STM/ST40Linux-1.0/devkit/sh4/lib /usr/lib/libjpeg.so ./.libs/libgdk_pixbuf-2.0.so \
	/opt/STM/ST40Linux-1.0/devkit/sh4/lib/libgmodule-2.0.so -ldl \
	/opt/STM/ST40Linux-1.0/devkit/sh4/lib/libgobject-2.0.so \
	/opt/STM/ST40Linux-1.0/devkit/sh4/lib/libglib-2.0.so -lm \
	-Wl,--export-dynamic -Wl,-soname -Wl,libpixbufloader-jpeg.so \
	-o .libs/libpixbufloader-jpeg.so
/usr/lib/libjpeg.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[3]: *** [libpixbufloader-jpeg.la] Error 1
make[3]: Leaving directory `/home/chinstrap/users/acister/work/packages/BUILD/gtk+-2.0.5/gdk-pixbuf'
...

I tried several solutions to this problem but each one ended up in creating some more problems. Given that we don't need some of the components that are built by a standard compilation, I decided to rewrite the complete build system from scratch using shell scripts instead of Makefiles.

Using the captured output of a local build as reference, I wrote a number of shell scripts, one for each directory where something needed to be built, that take care of building each original target. As all the build instructions are contained in a set of sh4-build.sh scripts that are added to the source tree, the spec file is deceptively simple.

Installation is managed by a similar set of scripts named sh4-install.sh. These scripts are run in the directories containing the needed files and take care of moving everything in the right place.

Using shell scripts instead of Makefile may seem less flexible but we must consider that package building is quite different from normal development. The whole system is meant to compile a fixed set of sources in one go with no interation or modification from the developer.


Conclusions

Maybe put here issues with the autotools????

Issues with the autotools

IS THIS THE RIGHT PLACE?

Almost all the problems encountered during this quest came from the four tools that are supposed to make the developers' life easier: autoconf, automake, libtool and pkg-config.

Here is a more detailed description af the issues I had with these tools when trying to cross compile GTK2.

Autoconf (and and the configure script)

  • The use of AC_TRY_RUN macros in configure.in simply forbids cross-compilation because the executable produced by the compiler for the test is for a different architecture (the target's one). AC_TRY_RUN should be avoided or, at least, a chance should be given of overriding the values it is needed for.

    The solution I've found to solve this problem is described in the GLib 2 for the target section.

  • The configure script generates the pkg-config files at the end of the configuration phase ignoring a possible definition of the make variable translate at install time. This variable can be used to change the name of the executables at install time, e.g. adding a common prefix.

    Ignoring the definition of this variable lead to wrong program names being written in these files. E.g. gcc insted of sh4-linux-gcc

Libtool

This is the program that gave me more problems than all the others together. I still can't believe that a simpler solution, or at least one that can be overridden, to the shared libraries problem can't be found. I'm particularly worried by the incredible complexity of this tool added by the number of supported architectures when most of the times only a handful of them are really useful.

Here are the main griefs I had with libtool:

  • It is very difficult to constrain to a subtree. This is the result of some hard-coded directory in its source code (/usr/lib.) Libtool ends up looking for libraries on the host often finding the wrong ones or not finding the correct ones.
  • The relink phase during installation is very obscure and annoying. Why is it needed? It consistently fails when tryied in a cross development environment.

    To fix this behaviour I had to the use of a custom script instead of the original libtool when installing. This simple script just by-pass the original libtool when invoked with a relink option.

  • Sometimes the .la files generated by libtool contain wrong paths. I had to fix them by hand using sed.

Automake

  • The glib-mkenums program name is hard-coded in Makefiles.am, why? The macro @GLIB_MKENUMS@ is available for substitution in configure and could be used by setting the environment variable with the same name.

Aclocal

  • The --print-ac-dir option should print all directories including the versioned one.
  • The -I option can't really be used to add directories to the search path because if a macro is defined in two places we get a "duplicate macro" error message. (E.g. GLIB2 both on the host and in our distro.)
  • The version number should be accessible alone and in a more standard format.
Previous   Contents   Next
Valid HTML 4.01! Last updated: 2004/06/18 16:13:39
© Copyright STMicroelectronics Limited, 2005
Printer