KernelNewbies:

What is cross compiling?

Cross compilation is where the compiler produces executable for running on a different platform. Let me explain it by using an example. Assume that PingWu wants to compile the linux kernel for an embedded linux system (based on say, powerpc). She has a ppc based board where already a linux kernel and applications are running.

Ping starts compiling the latest and greatest kernel from kernel tree. But soon she realizes that her embedded system, although pretty smart for the task it was designed to perform, has limited resources and would easily take a couple of hours just to compile the kernel with minimal options. At the same time she discovers that she has a workstation running linux with AMD64 dual core 8way processor with 128GB RAM. Linux kernel compiles in that machine within less than 5 minutes. (I tested it, believe me it took around 4:30 minutes for full compilation of linux 2.6.18-rc3). She compiles the kernel, but she immediately realized that the output from her workstation is for AMD64 arch, and would not run on ppc.

What she needs is a Cross Compiler -- A compiler runs in architecture A, producing output executable for architecture B. (substitute AMD64 for A and PPC for B in the above example).

== GCC and binutils in cross platform incarnations === For compiling the linux kernel, you require gcc and binutils. GCC is extremely smart and can produce output in a variety of architectures, but it must be instructed at the time of compilation of gcc itself. So is the case of binutils. (BTW, if you do not know what bin utils are, they are the basic binay utilities like the assembler, linker, loader ..etc. Assuming you are running a linux distro based on RPM (package manager),

[om@turyxsrv ~/work]$ rpm -qf /usr/bin/as
binutils-2.16.91.0.6-4
[om@turyxsrv ~/work]$ rpm -ql binutils-2.16.91.0.6-4
...
/usr/bin/ar
/usr/bin/as
/usr/bin/c++filt
/usr/bin/gprof
/usr/bin/ld
/usr/bin/nm
/usr/bin/objcopy
/usr/bin/objdump
/usr/bin/ranlib
/usr/bin/readelf
/usr/bin/size
...

Now you know how to check for the binutils and constituent files.

Getting a cross compiler

Lets come back to the problem. These files would (generally) produce output executables to run on different platforms. Easiest way to get a cross compiler is to download a precompiled one. There are many available on the net, including ELDK (Embedded Linux Development Kit -- by [http://www.denx.de/en/News/WebHome#NewsELDK40 Denx.de] ).This toolchain is available on various target platforms including ppc, arm ..etc.

Another great tool chain is available from [http://developer.osdl.org/dev/plm/cross_compile/ OSDL] (Randy Dunlap pointed it out. Thanks Randy). Follow the installation procedure for the cross compiler suite you choose to get it installed.

64bit/32bit compilers

GCC is capable of generating both 32 and 64 bit code (eg.for AMD64 and IA32, or PPC and PPC64) using a compiler flag (-m32/-m64). When you take part in kernel development, you might want to compile your patchsets for both 32 and 64 bit architectures. Cross Compilation comes to your rescue here too. Rather than trying to modify the kernel makefile options to produce 32 bit output using 64 bit compiler or vice versa, (I could not figure it out after spending a couple of hours :-( ), one should have a cross compiler to compile the kernel for 32 / 64 bit outputs on same platform.

Testing the setup

Once you have set up the cross compiler, you should test it using a small hello.c to make sure that compiler indeed works. What I did is,

[om@turyxsrv ~/prg/tmp]$ export cross=i686-unknown-linux-gnu-
[om@turyxsrv ~/prg/tmp]$ echo $cross
i686-unknown-linux-gnu-
[om@turyxsrv ~/prg/tmp]$ ${cross}gcc mathtest.c -o math
[om@turyxsrv ~/prg/tmp]$ file math
math: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.4.3, dynamically linked (uses shared libs), for GNU/Linux 2.4.3, not stripped

So, it is working.

Now lets configure and compile the linux kernel

[om@turyxsrv ~]$ cd src/i386-linux-2.6
[om@turyxsrv /home/src/i386-linux-2.6]$ uname -a
Linux turyxsrv 2.6.18-rc3 #3 SMP Sun Jul 30 11:54:32 PDT 2006 x86_64 x86_64 x86_64 GNU/Linux
[om@turyxsrv /home/src/i386-linux-2.6]$ make CROSS_COMPILE=i686-unknown-linux-gnu- ARCH=i386 xconfig
[om@turyxsrv /home/src/i386-linux-2.6]$ make CROSS_COMPILE=i686-unknown-linux-gnu- V=1 -j4 all

I used V=1 to make the compilation verbose and -j4 to make use of my 4CPU machine.

After the compilation, make prints the message,

Kernel: arch/i386/boot/bzImage is ready  (#1)

If you are still paranoid, make sure the architecture you compiled for is correct.

[om@turyxsrv /home/src/i386-linux-2.6]$ file vmlinux
vmlinux: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

All done. I compiled on AMD64 and the target kernel would run on i386.


["CategoryFAQ"]

KernelNewbies: FAQ/KernelCrossCompilation (last edited 2006-08-10 07:40:29 by OmNarasimhan)