HOWTO: Cross-compiling a 32-bit (i386) Linux kernel on 64-bit Machine (amd64)
Purpose: These days 64-bit hardware and Operating System are getting more and more common and affordable. Now if you are use to compile a custom Linux kernel on a regular Intel architecture 32-bit machine (i386) for a 32-bit machine itself then there were no issues. But now when you are trying to compile a custom Linux kernel for a 32-bit on your 64-bit machine things start getting different. One cannot directly compile a 32-bit kernel on a 64-bit machine in an easy fashion. I have asked in several forums but did not get a proper answers, so I decided to research on my own. In this blog post we will learn how to compile a 32-bit kernel on a 64-bit machine.
If you are looking for how to run a 32-bit graphical (X Windows) application on a 64-bit operating system, click here.
Terminology: Usually in the Linux world:
- i386 – Refers to 32-bit
- amd64 – Refers to 64-bit
Note: “amd64″ does not mean only 64-bit AMD machines. The term amd64 is used in general for all 64-bit machine – Intel, AMD and VIA. To give credit to AMD for first coming up with 64-bit architectures, the word amd64 is used.
Scenario: Here is my current scenario which I will be using throughout this entire blog post
Host Machine: AMD Athlon X2 Dual Core 64-bit machine with 64-bit Debian OS install
Target Machine: Intel Celeron 32-bit machine
Now, I would like to compile a Linux kernel for my Target machine on my Host machine. Typically people do these because usually Host machine are faster than than Target machine or just as in my case I have decided to compile all my Linux kernel on Host machine. However if you have installed a 32-bit OS (Operating System) on a 64-bit machine then you can just compile your kernel the way you use to do before. You don’t need to follow this post.
Step 1: Create a 32-bit debootstrap system
The fist step is to create a 32-bit Debian bootstrap system on your host machine. You can follow this link for step-by-step guide on how to do that.
The end result of this step will be that you will have a brand new 32-bit system in the following directory:
/home/kushalk/chroots/debian32
on your 64-bit machine
Step 2: Setup your kernel sources
Now just “chroot” into your bootstrap system gy giving the following command:
amd64# chroot /home/kushalk/chroots/debian32
debian32# cd /usr/src/
debian32# apt-get install linux-source-2.6.26
debian32# tar -xjvf linux-source-2.6.26.tar.bz2
and you are ready to start compiling the kernel
Note: Instead of downloading sources all over again from the Internet, you can also copy the source folder from your /usr/src/ directory on your host machine. Linux kernel sources are not 32-bit/64-bit dependent meaning that the same source tarball file can be used to compile 32-bit and 64-bit kernels.
Step 3: Configure your Linux kernel
Now either you can just create a default kernel .config file by :
debian32# cd /usr/src/linux-source-2.6.26
debian32# make defconfig
or else you can copy an existing .config file by:
debian32# cp </path-to-config-file/.config> .config
or else you can configure your kernel to generate a .config file by:
debian32# make menuconfig
Now if you want to use graphical kernel configuration like “make xconfig” or “make gconfig”, you won’t be able to do with the above setup so far. If you try to do you will end up getting following error messages:
debian32# make xconfig
scripts/kconfig/qconf arch/x86/Kconfig
No protocol specified
qconf: cannot connect to X server :0.0
make[1]: *** [xconfig] Error 1
make: *** [xconfig] Error 2
debian32#
We need to do some additional steps in order to get the graphical configuration screen which I will explain in my next post (see Step 5).
Step 4: Compile your Linux kernel
Now there are two ways to compile a Linux kernel – the “Standard” way or the “Debian” way which involves using “make-kpkg” utility. I usually compile the Debian way.
debian32# make-kpkg --initrd --append-to-version=-32bit kernel_image kernel_headers
Now go and grab a coffee and you should have your kernel ready in few minutes.
Now you can come out from your “chroot” environment and copy the kernel image back on your host system.
debian32# exit
amd64# cp /home/kushalk/chroots/debian32/usr/src/*.deb /root/
In the above command, I am copying all the *.deb files (which should be your compiled kernel and headers files) from my 32-bit bootstrap system to the “root” user directory on my host system (amd64). Although we used the notion of “32-bit system” it just means a directory which resides on your host system. Your 32-bit bootstrap system in on your 64-bit machine itself.
That’s it. Happy 32-bit’ing!

Free Email Subscription









June 5th, 2009 at 7:12 pm
[...] We have already seen how to create a debootstrap system and we also learned how to compile a 32-bit application (like Linux kernel) from within the debootstrap system in Debian Linux. [...]
October 23rd, 2009 at 12:05 pm
$ (echo ‘#! /bin/sh’; echo ‘exec gcc -m32 “$@”‘) >~/bin/i486-linux-gnu-gcc
$ chmod +x ~/bin/i486-linux-gnu-gcc
$ for i in ar ld nm objcopy strip; do
$ ln -s `which $i` ~/bin/i486-linux-gnu-$i
$ done
$ fakeroot make-kpkg –arch i386 kernel-image
Works for me…
Reply to this comment
Admin Reply:
October 26th, 2009 at 10:14 pm
I am now curious to try that. I will really appreciate if you can briefly explain what you are doing in the commands before the “fakeroot” command.
Thanks.
Reply to this comment
October 27th, 2009 at 10:31 am
Making sure that the necessary binaries are present for the target. They’re needed because make-kpkg does this:
make CROSS_COMPILE=i486-linux-gnu- ARCH=i386 prepare
Symlinking is mostly fine since the same binaries are normally used for x86 and amd64 anyway. The odd one out is the compiler, which needs “-m32″ (though I’ve not tested without this, it seems reasonable to specify it anyway for correctness; and the compiler will target amd64 by default).
Reply to this comment
Admin Reply:
November 3rd, 2009 at 12:37 pm
Hi Ds,
Now I do see what you are trying to do in your little script before fakeroot. However before I try that, I would like to know how to un-do the steps (in a clean manner) to restore it to the original state (for building amd64 kernels).
Reply to this comment
November 1st, 2009 at 9:00 am
Nice post, but I am wondering (a bit lazzy to try myself) if
$ linux32 make defconfig
$ linux32 make
would not do the job? Did you investigate this possiblity?
Reply to this comment
ds Reply:
November 1st, 2009 at 3:37 pm
That seems fine.
“fakeroot linux32 make deb-pkg” also works, but doesn’t provide the sometimes-useful “you’re replacing the running kernel – are you sure?” questions.
However, “fakeroot linux32 make-kpkg kernel-image” builds 64-bit (this is clear from what happens when it runs “make oldconfig”).
Reply to this comment
pat Reply:
November 2nd, 2009 at 10:18 am
I agree my answer would not work to build a debian package.
I did try however to build the kernel from the sources tarball, and it worked. I was even able to boot on it with another 32-bit system I have. The only problem is that the configuration is not easy, only console mode config worked…
And installing the modules is not that easy. So let’s keep my answer for the archives… ;-p
Reply to this comment
pat Reply:
November 2nd, 2009 at 10:22 am
Just thinking to it a bit late, but installing the modules will be much easier through a simple chroot.
Reply to this comment