Setting up a Cross Development Environment on Debian GNU/Linux

Debian

W. Borgert

Debian

Copyright 2002 W. Borgert. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.

Look for the latest version of this document: DocBook/XML and HTML

2002-11-10

Revision History
Revision 0.32003-03-11
Update to current versions of toolchain-source and dpkg-cross, patches removed.
Revision 0.22002-11-10
Added example for use with glib-2.0 and some explanations.
Revision 0.12002-11-09
Initial version.

Table of Contents

Introduction
Preparations
Setting up binutils, libc and the compiler
binutils
libc
gcc
A little test
Setting up additional cross development libraries
Creating dummy packages
Patch the tools
Install libraries
Try it out
Thanks

Introduction

You have a new shiny GNU/Linux-based PDA? Or a new embedded controller board running a PowerPC processor? Now you want compile your favourite software for the gadget on your PC? While this has been a difficult to accomplish task in the past, you can do it much easier today. You just need Debian GNU/Linux and some of its nice little tools, most importantly toolchain-source and dpkg-cross.

In this article, I will explain how to set up a cross development environment for the ARM platform including the use of libglib2.0. The ARM processor can be found in a number of embedded devices and PDAs, e.g. the Zaurus and the iPAQ.

Note

All packages and versions are related to Debian SID (a.k.a. stays in development, a.k.a. unstable). Things may change. I am working on the i386 platform, but I have the hope, that things are not entirely different on other platforms.

Note

I use the traditional # for the root prompt and $ for the non-root prompt.

Preparations

First, install toolchain-source 3.2-6 or newer and dpkg-cross 1.13.2 or newer. Because toolchain-source depends on dpkg-cross, the following command will do:

# apt-get install toolchain-source

The toolchain-source package contains the source code of the current gcc and binutils. Additionally, it provides commands assisting in building cross compilers and binutils.

The dpkg-cross package is a tool for installing libraries and headers for cross compiling in special directories.

I had a problem with building gcc with autoconf version 2.54 ("configure.in:2118: /usr/bin/m4: ERROR: Recursion limit of 1024 exceeded, use -L<N> to change it"), so I recommend to:

# apt-get install autoconf2.13

For building the actual cross development packages, you will need fakeroot or a similar program. Because fakeroot will be used by default, just do this:

# apt-get install fakeroot

The only configuration, that is necessary now, is to change the crossbase in the file /etc/dpkg/cross-compile. The default value /usr/local should be changed:

crossbase = /usr

Setting up binutils, libc and the compiler

binutils

Now unpack and build binutils and compilers.

$ cd /usr/src/
$ EMAIL='you@there.org' tpkg-make arm-linux

New directories binutils-arm-linux-2.13.90.x.y/ and gcc-arm-linux-3.2.z/ appear.

Adjust the user name in {binutils-arm-linux-2.13.90.x.y,gcc-arm-linux-3.2.z}/debian/{changelog,control}, if necessary. You might get an error when signing the package, if the user name is not correct. If you have to pass parameters to the configure or make process of binutils or make, change the files {binutils-arm-linux-2.13.90.x.y,gcc-arm-linux-3.2.z}/debian/rules. E.g. the default configuration builds only the C compiler, which is just what I want. The generation of the C++ compiler failed for me, because of compilation errors in the libstdc++-v3, but if want to try it, you have to add C++ support to the configuration options in debian/rules:

--enable-languages="c c++"

Now do:

$ cd binutils-arm-linux-2.13.90.x.y/
$ debuild

This will configure, compile and build the cross binutils. To build the compiler, you have to install the resulting package first:

# debi

libc

The compiler needs also the target system C library to build. This library can easily be installed using tpkg-install-libc.

# tpkg-install-libc arm-linux

This command will download the libraries for the arm-linux platform from the british Debian server ftp.uk.debian.org. To use e.g. the german server, try:

# TPKG_SERVER=ftp.de.debian.org tpkg-install-libc arm-linux

The downloaded packages will automatically converted and installed by dpkg-cross.

gcc

Now do:

$ cd ../gcc-arm-linux-3.2.z/
$ debuild

Again, the package installs via:

# debi

Now you should have a perfect cross development environment:

$ dpkg -l "*-arm-*"
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name           Version        Description
+++-==============-==============-============================================
ii  binutils-arm-l 2.13.90.0.18-1 Binary utilities for cross-developing for ar
ii  gcc-arm-linux  3.2.3.cvs20030 The GNU C compiler as cross compiler for arm
ii  libc6-arm-cros 2.3.1-14       GNU C Library: Shared libraries and Timezone
ii  libc6-dev-arm- 2.3.1-14       GNU C Library: Development Libraries and Hea
ii  libdb1-compat- 2.1.3-7        The Berkeley database routines [glibc 2.0/2.

A little test

You may test the newly installed environment by unpacking a simple, but famous program:

$ cd /usr/src/
$ apt-get source hello
$ cd hello-2.1.1
$ CC=/usr/bin/arm-linux-gcc ./configure --host=arm-linux
$ make -k

Don't get fooled by the fact that the last step of the build process will produce one error. The build process of hello is not completely cross compile enabled. The manual page can only build after a native compile. Just don't care:

$ file ./src/hello
./src/hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux
2.2.0, dynamically linked (uses shared libs), not stripped

Copy the binary to your target system and enjoy the friendly greeting.

Setting up additional cross development libraries

There are not many programs a user really wants without the need for more library dependencies than just the standard C library. A typical additional library is glib2 which is used by GTK+ and GNOME.

Before you can start with the library, you have to analyse its dependencies:

$ apt-cache show libglib2.0-0|grep ^Depends:
Depends: libc6 (>= 2.3.1-1)
$apt-cache show libglib2.0-dev|grep ^Depends:
Depends: libglib2.0-0 (= 2.0.7-1), libc6-dev | libc-dev, pkg-config

Creating dummy packages

The dependencies of libc6 and libc6-dev are already fulfilled by libc6-arm-cross and libc6-dev-arm-cross, the dependency libglib2.0-0 will be fulfilled anyway. That leaves pkg-config. A cross version of pkg-config does not make sense, because the only important thing is the output of the command itself. This depends on the contents of the .pc files. Therefore it is sufficient to create a dummy package that depends on pkg-config. Install the equivs package:

# apt-get install equivs

Now create a control file pkg-config-arm-linux:

Section: devel
Priority: optional
Standards-Version: 3.0.1

Package: pkg-config-arm-cross
Version: 0.15.0-2
Maintainer: You <you@there.org>
Depends: pkg-config
Architecture: all
Description: Dummy pkg-config for arm-linux
$ equivs-build pkg-config-arm-linux

And install the package:

# dpkg -i pkg-config-arm-cross_0.15.0-2_all.deb

Similar actions are necessary for tools, that are not platform-dependent, such as bison, flex, or indent.

Patch the tools

Apply the following patch to tpkg-install-libc:

-LIBSET='libdb1-compat$ libc6$ libc6.*-dev$'
+LIBSET=${LIBSET:-'libdb1-compat$ libc6$ libc6.*-dev$'}
 
-        ppc|powerpc*)
+        ppc*|powerpc*)

The patch allows the user to install other libraries than libc6 via the environment variable LIBSET.

Apply the following patch to dpkg-cross (maybe not necessary anymore - have to check):

--- dpkg-cross.orig	2002-11-10 01:32:28.000000000 +0000
+++ dpkg-cross	2002-11-10 01:34:02.000000000 +0000
@@ -339,17 +352,11 @@
 	# move libs to their location
 	foreach $dir ( @libdirs ) {
 		-d "$tmpdir/$dir" || next;
-		# remove subdirs in .../lib, don't need them
 		my @dirfiles;
 		for $file ( <$tmpdir/$dir/*> ) {
-			if (-d $file) {
-				system "rm -rf $file";
-			}
-			else {
-				$file =~ s,^\Q$tmpdir/$dir/\E,,;
-				push( @files, $file );
-				push( @dirfiles, $file );
-			}
+			$file =~ s,^\Q$tmpdir/$dir/\E,,;
+			push( @files, $file );
+			push( @dirfiles, $file );
 		}
 		for $file ( @dirfiles ) {
 			print "  $dir/$file\n" if $verbose >= 2;
@@ -377,6 +384,18 @@
 			|| warn "$progname: Cannot create symlink $file -> $basename\n";
 	}
 

The patch ensures, that the fixed paths in the .la and .pc are adjusted to the cross development environment paths.

Install libraries

Try to install libglib2.0-0 and libglib2-dev:

# LIBSET='libglib2.0-0$ libglib2-dev$' TPKG_SERVER='ftp.de.debian.org' tpkg-install-libc arm-linux ''

The dollar signs are necessary for the tool as are the single quotes.

The cross compilation environment should now be complete:

$ dpkg -l "*-arm-*"
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name           Version        Description
+++-==============-==============-============================================
ii  binutils-arm-l 2.13.90.0.4-1  Binary utilities for cross-developing for ar
ii  gcc-arm-linux  3.2-1          The GNU C compiler as cross compiler for arm
ii  libc6-arm-cros 2.2.5-14.3     GNU C Library: Shared libraries and Timezone
ii  libc6-dev-arm- 2.2.5-14.3     GNU C Library: Development Libraries and Hea
ii  libdb1-compat- 2.1.3-7        The Berkeley database routines [glibc 2.0/2.
ii  libglib2.0-0-a 2.0.6-1        The GLib library of C routines (for cross co
ii  libglib2.0-dev 2.0.6-1        Development files for the GLib library (for 
ii  pkg-config-arm 0.14.0-1       Dummy pkg-config for arm-linux

Try it out

You can see the CFLAGS for cross compilation easily:

$ PKG_CONFIG_PATH=/usr/arm-linux/lib/pkgconfig pkg-config --cflags glib-2.0
-I/usr/arm-linux/include/glib-2.0 -I/usr/arm-linux/lib/glib-2.0/include

For packages, that come with a simple Makefile, use CC and CFLAGS=`pkg-config --cflags glib-2.0` etc., compilation is straight forward:

$ CC=/usr/bin/arm-linux-gcc \
  PKG_CONFIG_PATH=/usr/arm-linux/lib/pkgconfig make

For packages based on autoconf, it should be easy as well:

$ CC=/usr/bin/arm-linux-gcc \
  PKG_CONFIG_PATH=/usr/arm-linux/lib/pkgconfig ./configure
$ make

Unfortunately, not all packages are build in a way, that supports cross compilation. For these packages, you should fix the build process and send patches to the packages authors.

Thanks

To Roman Hodek for dpkg-cross, to Jeremy Nimmer for patches to dpkg-cross, and to Hakan Ardo for toolchain-source and his help.