How to compile a custom Debian kernel

Since I have been asked by a few people, I’m going to show you how to compile your own Debian kernel package from vanilla (kernel.org) sources, customizing it to your hardware.

Introduction

I wanted to compile a customized kernel for long but never got around to it. Since the touchpad on my ASUS Zenbook UX21 does not work very well with a standard kernel (as of February 2012) I had to patch it, compiling a kernel for the first time.

In this article I’m going to show you how you can do the same, but since I’m no expert I can only tell you what I’ve done, which may not work for you at all. You need to be comfortable with the console though. If you have any questions, just post a comment and I’ll try to answer them.

Installing needed tools

First of all you will need to install the following packages to download and build the kernel:

kernel-package libncurses5-dev fakeroot wget bzip2 build-essential

Getting the sources

This is the easiest part, just go to kernel.org and choose which version you want to use. I personally use the mainline kernel, but you can choose a stable version if you like.

$ cd ~/src
$ wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.2.8.tar.bz2
$ tar xjf linux-3.2.8.tar.bz2
$ cd linux-3.2.8

Configuring the kernel

Now for the fun part: making your new kernel config. Depending on whether you want to customize your kernel for your hardware or only apply patches you can skip the second step in this section and fast-forward to Applying patches.

Copy and update the current configuration

Depending on what kernel you’re currently using you might want to start with your current configuration. I’ve never done it any other way:

$ cp /boot/config-`uname -r` .config

To update the config to the new kernel by showing you any new options, type the following. You can skip this step, if your kernel is much older you will get a lot of questions.

$ make oldconfig

Customize your kernel configuration

Before continuing with this step, you may want to determine what modules need to be built into the kernel for your specific hardware. The method I used is to use lsmod to get the currently loaded modules, look for the corresponding option in the configuration and set it to Y.

$ make menuconfig

will show a nice menu where you can navigate the options. This is the lengthy part, you will have to go through all the options and determine if you want to keep them or not. I suggest you read the help text to any option you don’t know by pressing H. You can search options by pressing / to look for the modules you need to build in. This is going to take a long time, so fix yourself a cup of coffee or two.

You can disable any drivers you don’t need, I suggest you build drivers which you are not sure about as modules, so they can be loaded if needed (for example for USB storage devices and such). If you don’t need that many drivers (for example for a laptop, the hardware doesn’t change much) I suggest you disable initrd support by setting BLK_DEV_INITRD to false, that should give you a second or two when booting.

Applying patches

One of the two main reasons for building your own kernel is that you want to apply patches. You can either edit the source files directly or use a patch file. The first one I will not show, if you don’t know how to do that you most likely don’t want to build a kernel yourself 😉

To apply a patch file, use the following commands. The first one does a dry run, only showing what would be done so you can fix any errors before messing anything up.

$ cat /path/to/your.patch | patch -p1 --dry-run
$ cat /path/to/your.patch | patch -p1

Depending on your patch file you may need to adjust the p parameter, it defines how many subdirectories in the patch file are skipped when looking for the file to patch.

Compiling the package

In order for you to be able to install the kernel on other machines or give it to someone else (and also for your own convenience), you are going to create a Debian kernel package. This is done automatically when compiling the kernel, using either of these two commands. The first one uses fakeroot to make the package (necessary for files belonging to root to be packaged), the second runs as root. It’s just a matter off taste though, it makes no difference for the final package.

$ make-kpkg -j 4 --rootcmd fakeroot --initrd --append-to-version -ux21 --revision 20120228 kernel_image kernel_headers
# make-kpkg -j 4 --initrd --append-to-version -ux21 --revision 20120228 kernel_image kernel_headers

Let’s go over the options to the make-kpkg command:

  • -j 4 » This causes the compilation to run on more than one CPU core. With this option the build was three times as fast on my laptop. You should set this to the number of cores your CPU has (HT included).
  • --rootcmd » Specifies which command to use to become root for file operations, no need to change this.
  • --initrd » If you chose not to use an initrd, just leave this option out.
  • --append-to-version » This gets appended to the kernel version and shows up in GRUB, aptitude and uname -r. It should start with a dash.
  • --revision » This specifies the version of your package shown in aptitude and must be numeric. I suggest you use the date to quickly tell which kernel is the newer one.
  • kernel_image, kernel_headers » These specify the build targets, which packages are created. There are also kernel_doc and kernel_source.

The packages are created in the parent directory. To install them, go to the parent directory and do:

# dpkg -i linux-image-3.2.8-ux21_20120228_amd64.deb
# dpkg -i linux-headers-3.2.8-ux21_20120228_amd64.deb

Depending on your architecture, the amd64 part may be something else.

That’s it. Just reboot and enjoy the fast system start 🙂

One thought on “How to compile a custom Debian kernel

  1. I tried this awesome tutorial with the current stable kernel 3.3.4 on a pentium 4 (took me about 3.5 hours compile time). Some error occured while make-kpkg. It said Documentation/lguest is neither a file nor a directory. The solution was a symbolic link from Documentation to /tools/lguest:
    ~$ cd Documentation
    ~$ ln -s ../tools/lguest
    The rest worked fine for me, great tutorial!

Leave a Reply to Schurli Cancel reply

Your email address will not be published. Required fields are marked *