cross compiler mini howto
Note added in 2004
The text below is several years old by now. Some notes and comments are sligtly dated. The basic procedure to build a cross compiler is still the same through, so if you apply some common sense it should still work fine. In case you don't know what egcs is: that was a fork of the gcc compiler. Enjoy reading.
Introduction
This is a short description how to build and use a cross compiler. I've build myself a intel-to-sparc crosscompiler, becauce compiling kernels on a Pentium Pro takes much less time than compiling on my good old Sparc SLC. All example commands are for that setup. Both boxes are running RedHat 5.1
Step one: build binutils
First, you need cross-linker and cross-assembler for your target platform. Therefore, the first step is to compile the binutils.
If you have the RedHat CD's offhand, you can pull the sources out of the rpm:
$ rpm2cpio /vol/cd2/SRPMS/binutils-2.9.1.0.4-2.src.rpm | \ cpio --extract
Otherwise you can download them from your favorite sunsite-mirror.
Now untar the binutils source code ("tar xvzf binutils-2.9.1.0.4.tar.gz"), change to into the new directory and configure the sources for cross-compiling:
$ ./configure --prefix=/usr/local --target=sparc-linux \ i486-redhat-linux
Type "make" to compile the whole thing now. Time for a break, this will take some time. When it is finished, install it (as root) with "make install".
You should have the programs installed in /usr/local/bin now:
bogomips root /usr/local/bin# ll sparc-linux-* -rwxr-xr-x 1 root root 209428 Aug 16 10:20 sparc-linux-addr2line* -rwxr-xr-x 2 root root 210204 Aug 16 10:20 sparc-linux-ar* -rwxr-xr-x 2 root root 376860 Aug 16 10:20 sparc-linux-as* -rwxr-xr-x 1 root root 21004 Aug 16 10:20 sparc-linux-c++filt* -rwxr-xr-x 1 root root 36104 Aug 16 10:20 sparc-linux-gasp* -rwxr-xr-x 2 root root 337620 Aug 16 10:20 sparc-linux-ld* -rwxr-xr-x 2 root root 216516 Aug 16 10:20 sparc-linux-nm* -rwxr-xr-x 1 root root 325244 Aug 16 10:20 sparc-linux-objcopy* -rwxr-xr-x 1 root root 394076 Aug 16 10:20 sparc-linux-objdump* -rwxr-xr-x 2 root root 210204 Aug 16 10:20 sparc-linux-ranlib* -rwxr-xr-x 1 root root 195300 Aug 16 10:20 sparc-linux-size* -rwxr-xr-x 1 root root 194860 Aug 16 10:20 sparc-linux-strings* -rwxr-xr-x 2 root root 325244 Aug 16 10:20 sparc-linux-strip*
You should have a new directory called /usr/local/sparc-linux too:
bogomips root ~# ls /usr/local/sparc-linux bin/ lib/
Step two: install include files and libraries
The new /usr/local/sparc-linux is the directory where the cross-compiler will look for libraries and includes first. So they should be installed there. I did it this way:
- create and go to some temporary directory
- unpack the glibc rpms there:
$ rpm2cpio /path/to/RPMS/glibc-2.0.7-17.sparc.rpm | \ cpio --extract --make-directories $ rpm2cpio /path/to/RPMS/glibc-devel-2.0.7-17.sparc.rpm | \ cpio --extract --make-directories
- copy the includes
$ cp -a usr/include /usr/local/sparc-linux
- add the kernel headers
$ cp -a /usr/src/linux/include/linux \ /usr/local/sparc-linux/include/linux $ cp -a /usr/src/linux/include/asm-sparc \ /usr/local/sparc-linux/include/asm
Recent kernels also need asm-generic copyed. - copy the libraries
$ cp -a lib/* /usr/local/sparc-linux/lib $ cp -a usr/lib/* /usr/local/sparc-linux/lib
- remove the temporary directory
Now we have to fix a few things. There are some broken symbolic links, becauce we have everything in a single directory and not splitted into /lib and /usr/lib. I am to lazy to do this by hand and did it with a small script:
$ cd /usr/local/sparc-linux/lib $ ls -l | grep "../../lib" | sed 's|../../lib/||' | \ awk '{ print "ln -sf", $11, $9 }' | tee fixit $ sh fixit $ rm fixit
Another pitfall is the libc.so. This isn't a real shared library, but a linker script (simple text, use your favorite editor for editing). The paths in that file must be fixed there too, using your hosts's /lib/libc.so will not work for cross-compiling. The same might be true for other shared libs as well, recent libpthread.so for example (reported by Jochen Friedrich, thanks).
Step three: The compiler itself
I used egcs here, again with the sources from the RedHat CD. Same procedure as with the binutils: pull the sources out of the rpm, untar them, change to the new egcs-1.0.2 directory.
The rpm came along with a few patches, so I applied them before continuing:
$ for file in ../egcs*patch; do patch -p1 < $file; done
Again, configure it as cross-compiler. gcc doesn't like being built inside its source dir, so we need to make a build directory for it:
$ mkdir build-dir $ cd build-dir $ ../configure --prefix=/usr/local --target=sparc-linux \ --with-gnu-ld --with-gnu-as i486-redhat-linux
Type "make" to compile it. If you got the include- and library installation (see above) right, it should compile completely out-of-the-box. Install your new cross-compiler (as root) with "make install".
Step four: test if it worked (optional)
You have the source code for the well know "hello world" program on your had disk, havn't you? If not, it is time to write one now. If you are lazy, you can download GNU hello. Ok, test it:
Intel box:
bogomips kraxel ~/src# uname -a Linux bogomips.isdn.cs.tu-berlin.de 2.1.115 #5-vger \ Fri Aug 14 21:54:36 CEST 1998 i686 unknown bogomips kraxel ~/src# sparc-linux-gcc -o hello hello.c bogomips kraxel ~/src# file hello hello: ELF 32-bit MSB executable, SPARC, version 1 bogomips kraxel ~/src#
Sparc box:
eibau kraxel ~/src# uname -a Linux eibau.isdn.cs.tu-berlin.de 2.1.115 #2-vger \ Sun Aug 16 00:56:16 CEST 1998 sparc unknown eibau kraxel ~/src# ./hello hello world! eibau kraxel ~/src#
Cool, test successfull. You have a full-featured cross-compiler now.
Additional libraries
If you are going to cross-compile some packages, they might miss some libraries. Just copy them (both includes and libraries od course) to /usr/local/sparc-linux/[include|lib]. Or cross-compile them too :-)
Cross-compiling your linux-kernel
As you can see...
eibau kraxel ~# cat /proc/version Linux version 2.1.115 (kraxel@bogomips.isdn.cs.tu-berlin.de) \ (gcc version egcs-2.90.27 980315 (egcs-1.0.2 release)) \ #2-vger Sun Aug 16 00:56:16 CEST 1998 eibau kraxel ~#
... my sparc runs a kernel which is cross-compiled on the intel box.
Cross-compiling your kernel is easy. Becauce I don't like typing long command lines, I've defined a alias:
bash$ alias smake='make ARCH=sparc CROSS_COMPILE=sparc-linux-'
Compiling isn't much different from a normal compile, just use the new alias instead of the normal make:
bash$ smake config [ ... answer all the questions here ... ] bash$ smake clean dep && smake boot modules
That's all. Happy compiling!