Building custom kernel for Ubuntu (also generate .deb package)
Updated 20-Jun-2013 : Building kernel deb package [ jump to this ]
This is a final how-to of this great year 2012, where I will show you how to compile a linux kernel and boot it on your linux box(it doesn’t matter which distro you use).
To build the linux kernel, you will need the kernel source first. The best place to get the latest stable and unstable linux kernels is www.kernel.org. The latest stable kernel release at the time of this writing is 3.7.1. Go ahead and download the tarball for the latest kernel release(preferrably a stable release). Downloading the kernel source on a decent broadband connection is going to take a while, so sit back and relax. I personally prefer to clone the git repository for the kernel source, so everytime there is a kernel update, I don’t need to download the entire kernel source. There is however no need to download the entire kernel source after an update, even while using a tarball. You can as well get a patch and apply it. Just to keep things simple, let us suppose you downloaded the tarball and extracted it somewhere, say to ~/linux-stable
Now you are ready to start building your new kernel. However, to build a linux kernel, you need to configure the kernel. Basically what this means is that, you need to tell the build system, what the kernel must include within itself and what must be built as modules and what is not neededin the kernel build. For example, you must specify what drivers you need for the hardware on your computer, etc. There are more than a thousand configuration options for the kernel, and it can be a daunting task to specify every single one of them on your own. The solution is to use the configurtion of your current kernel(i.e, the configuration of the kernel that is provided as part of the linux distro you are using). This configuration file should be named .config and must be present in the top src directory of the kernel.
So go ahead and copy the present kernel’s config as shown below. The current kernel’s config can be found in /boot with a name starting with config- followed by the kernel version.
$ cp /boot/config-* ~/linux-stable/.config
The new kernel may include options not found in your current kernel and thus there may be a few configuration options that you need to still specify.
$ cd ~/linux-stable
$ make oldconfig
You will be prompted with quite a few questions that will further configure your new kernel. If you are not sure what to answer to those questions, you can select the default by simply pressing the Enter key for each of the questions. Once the kernel configuration is complete you are ready to actually start compiling the linux kernel.
$ make -j`cat /proc/cpuinfo | grep -c processor`
Sit back and relax as the build is going to take a lot of time, especially when you use the configuration of your current kernel, because your current kernel configuration builds drivers for almost every hardware imaginable(even though you wouldn’t need them), because your distro is aimed at a large audience. Using the current kernel’s configuration is the safest way to build the kernel and get it to boot, however, you may try to modify the kernel configuration in ~/linux-stable/.config to suit your needs. The above command builds the kernel image as well as the kernel modules that get loaded dynamically. Now, all that is left is to install the new kernel image and kernel modules and to get the bootloader(ex: GRUB) to recognize and boot the new kernel the next time you boot your computer.
$ sudo make modules_install install
The above command installs the kernel image in the /boot directory, generates any initrd(initial ram disk) that is needed by the kernel during boot, generates a map file by the name of System.map(similar to a symbol table for the kernel) and also copies the configuration for the new kernel into the /boot directory(so that you may reuse it later to build another kernel, just as we did). It also modifies the bootloader configuration for you automatically, so that the bootloader(ex: GRUB) recognizes the new kernel. The kernel modules are installed into /lib/modules with the kernel version as the name and are linked to the kernel image. The kernel headers are installed into /usr/src.
That’s it. You have now succesfully compiled and installed a new kernel, albeit without any modifications of your own to the kernel. You can boot into the new kernel by holding down the shift key after the BIOS message during reboot to show the bootmenu of the bootloader where you can select the desired kernel version to boot into(the latest kernel version is selected for boot automatically). After boot, you can verify that you are indeed running the kernel that you just built by running ”$ uname -r” in a terminal which will show you the kernel version you are currently using.
If you find that you are unable to boot into the new kernel, don’t weep(you might have got some configuration option wrong), there is always backup. You can always boot into the kernel that your distro supplied by selecting it in the bootmenu of the bootloader during boot.
Should you decide that you no longer need a particular kernel version, you can completely get rid of it by deleting the corresponding kernel’s config, vmlinuz, System.map and initrd from the /boot folder and the corresponding kernel modules from /lib/modules and the kernel header from /usr/src. Once you are done deleting these files, all that remains is to update the bootloader by running ”$ sudo update-grub2”.
Should you decide to rebuild the new kernel from scratch run ”$ make mrproper” in ~/linux-stable to clean the kernel configuration and all the files that have already been built and you are ready to start all over again.
Happy hacking :) and happy new year :)
UPDATE : 20-Jun-2013
Building your custom kernel as a .deb package
If you find that compiling the kernel is taking too long on your computer, and have another faster, more powerful computer at your disposal, you can build your custom kernel as a .deb package on the faster computer, copy the .deb packages to the other computer and install your custom kernel there. You can even use the same .deb packages to install the custom kernel on other machines.
On the faster machine :
$ cd ~/linux-stable
$ make-kpkg clean
$ export CONCURRENCY_LEVEL=24 #change according to no. of CPU cores
$ fakeroot make-kpkg --initrd --append-to-version=-custom \
kernel_image kernel_headers modules_image
The above export and make-kpkg commands can be combined into a single command like below
$ fakeroot make-kpkg -j24 --initrd --append-to-version=-custom \
kernel_image kernel_headers modules_image
After –append-to-version= you can write any string that helps you identify the kernel, but it must begin with a minus (-) and must not contain whitespace.
After building is complete, you will find two .deb packages in the parent dir of the kernel source tree. Copy them to your other computer where you want to install the custom kernel.
On the slower machine (where you want to install custom kernel) :
$ sudo dpkg -i linux-image-*
$ sudo dpkg -i linux-headers-*
This step will also make an initrd image as well as modify the grub config for you automatically just as before. All you have to do now is reboot and enjoy your new kernel.