How to compile the Linux kernel

Posted at 4:38pm on Friday March 12th 2010

Do you want to remove bloat from your Linux installation? Are you looking to enable extra features that aren't provided by your distro? Fancy trying some of the cutting-edge patches doing the rounds? You'll need to recompile your kernel, and while it might look like black magic if you've never done it before, it's actually pretty straightforward. Read on for everything you need to know...

There is a phrase guaranteed to strike terror into the heart of new Linux users, especially those who are wary of venturing too far from the GUI. It is simply: "Recompile your kernel and..." To the unitiated, this is a rite of passage daunting enough to rival lion killing or scarification. To run a home-brewed kernel is to enter the realm of the hardcore Linux user.
But leaving aside matters of pride, why should you compile your own kernel? There are a number of possible answers:

To remove bloat Distro kernels generally support a wide range of hardware, most of which you probably haven't even heard of.

To enable extra features or drivers Murphy's Law implies that in spite of the previous statement, the one item that will not be included will be the hardware you just bought.

To use a newer kernel than your distro provides You might want to do this for later hardware support, more security or just because you want to.

To patch the kernel There are several patches that have not yet made it into the main kernel tree; some never will. If you want to use the special real time kernel (-rt series) or one of many other patches, you'll have to patch the source and then compile your own kernel.

As we'll show you in this tutorial, compiling a kernel isn't very different from compiling most other packages: first you run the configuration script, followed by make to compile the software, then you install it. The main difference is that the configure stage is usually interactive. Another difference is that each time you compile a new kernel, it is installed alongside the previous one, so if it doesn't work you can still boot from another, working, kernel.

Take root

Although it is possible to patch, configure and compile kernel source as a normal user, you need to be root to install it. For the sake of convenience, we have assumed that you will be running all of the commands given in this tutorial in a root terminal. Some distros have an option to open a root terminal in their menus; otherwise open a normal terminal and type su - followed by the root password. Ubuntu does not allow this, so instead use the command sudo -i and give your user password.

To the source

Before we can begin, you need to install the kernel source. To start with, we will use the source that matches your existing kernel, because this will already have a working configuration that we can use as a starting point. Using your distro's package manager, install the correct package. The name varies between distros but is usually something like linux-source or kernel-source. To find the version of the running kernel, use the terminal command

uname -r

You also need to install a compiler and associated tools; installing GCC should pull in everything you need. Some distros provide a development group of packages; if you run Ubuntu you should install the build-essentials package, which pulls in a few other packages as dependencies.
Linux source code is usually installed in /usr/src/linux-version-number, with a symbolic link to /usr/src/linux. If your distro does not create the link, do so yourself with

cd /usr/src
ln -s linux-2.6.xyz linux

Note that in Ubuntu, installing the linux-source packages drops the .tar.bz file into /usr/src, so you'll have to extract it before making the link.

Because we are using the existing configuration as a starting point, we must make sure that there is a copy of the configuration file in /usr/src/linux. The file is called .config; if it isn't present, there will probably be a copy stored in /boot or as part of the linux headers package. Running locate .config should find it for you, then copy it to /usr/src/linux. In Ubuntu 9.10, for instance, the file is /boot/config-2.6.31-14-generic (version numbers may vary), so copy that to .config in the source directory.

Once you have installed the source, you can start configuring it by executing the following commands in a root terminal. If you are using an X terminal, you will find it easier if you set its window to its maximum size.

You are now in the Ncurses configuration tool. Spend some time browsing around and trying out various options (navigate with the cursor keys). You will be asked if you want to save your kernel configuration when you exit; unless you say Yes, you can experiment all you want without affecting anything. Most of the options are fairly obvious. Any item ending with ‘--->' leads to a sub-menu, which you can see with Enter. Exit actually takes you back up a level (that is, it exits the current level), and it only exits the program itself when at the top level. You can use the Esc key for Exit.

It is usual for items to be in one of three states, indicated with *, M or nothing. The * means the item will be built into the kernel, M means it will be compiled as a loadable kernel module, and a blank space means the option is disabled. You can select these states with the Y, M and N keys respectively, or use the space bar to cycle between the available choices. Another key that you will be using - rather heavily the first few times you compile a kernel - is ?, which brings up help text about the current item.

There is one other key you must remember. This is the / key. There are many options in the kernel configuration, several layers deep, and finding the one you want can be difficult. Pressing / enables you to search for the relevant option.

Pruning the kernel tree

Once you have spent some time familiarising yourself with the options (we don't mean to hurry you), let's try building a new kernel with some unnecessary options removed. Keep hitting Exit until you are asked if you want to save the changes. Say No, then restart make menuconfig. Now, thoughtful distro teams tend to build in support for just about everything, to make sure their distro runs on as wide a variety of hardware as possible. So let's start by undoing their good work and removing some of the redundant drivers.

Go to Device Drivers > Network Device Support > Ethernet (10 or 100Mbit) to see all the network card drivers installed in your kernel. You probably only need one or two, so deselect all the ones that don't apply to hardware that you're actually going to use. If you're in doubt, the lsmod command will show the modules that you currently have loaded, and the Help file of each item will give the name of the module it covers. Repeat the process in the Ethernet (1000Mbit) and wireless LAN sections. You could also remove support for all the sound and video cards that you do not own, but it is best to proceed slowly, so we'd recommend that you leave this for another time. Press Exit until you actually do exit, this time saving the kernel configuration.
Now it is time to build and install your new kernel with

make all
make modules_install install

(Note: on a multi-core machine you can run 'make -j4 all' for the first command to run multiple compilation processes at the same time.) These commands perform three steps: first they build the new kernel and all its modules, then they install the modules to /lib/modules/kernel-version, and finally install the kernel itself to /boot. Before you do anything else, check that your bootloader is correctly set up to boot either this or the previous kernel. If you look in /boot you will see that make install copied the new kernel there.

Depending on your distro, make install may have done more for you. For example, distros that use the Debian installkernel script, which include Gentoo as well as the various Debian-based distros, also create a symlink for the new kernel to vmlinuz and from the previous kernel to vmlinuz.old. Others, such as Mandriva, only copy the kernel and associated files. To save typing, you can run this short shell script to set up the links on such distros:

If you edit your bootloader configuration to have two entries for these symlinks, vmlinuz and vmlinuz.old, you will always be able to boot either of the kernels. With Grub, you would need something like this in /boot/grub/menu.lst:

If you use Lilo you should make similar changes to their configuration and remember to run Lilo after installing a new kernel. Debian's installkernel and the above script both take care of this for you.

Customisation traps

You can substantially reduce the size of your kernel, which also reduces the memory it occupies and the time it takes to load, by removing unnecessary code. It is a rather liberating experience, but don't go too far. Only remove items you are sure you do not need. Remember that your previous kernel is still available, so if things go wrong and you can't even boot, select the older kernel from the boot menu.

There are a couple of traps for the unwary that can prevent a system booting. When choosing which filesystems to include, make sure the filesystem used by your root partition is compiled into the kernel, not as a module (see the Modules Or Built In box, below, for more detail). Also make sure you have included support for your IDE, SATA or SCSI chipset; again, this must be built in, not a module. Distro kernels can get away with building critical code as modules because they load all of these from an initial ramdisk (initrd). Your distro probably uses an initrd file in /boot, which will be specified in your bootloader's configuration file.

Modules or built in?

The Linux kernel is monolithic, originally intending all drivers to be part of the kernel. But as the kernel grew, this became unwieldy and loadable modules were introduced. These exist as separate files on the disk and are loaded into the kernel when needed. This creates a great deal of flexibility - and much debate on whether drivers should be built into the kernel or separate modules. The answer depends on your computer and how it will be used.

As an example, my laptop has two network interfaces, wired and wireless. I may use either or neither at any time, so it makes sense to use modules. On the other hand, my desktop computer has a single, wired interface that is always in use, so it may as well be part of the kernel since it will always be loaded.

Running with no modules at all, and disabling module loading in the kernel, is considered slightly more secure. This is a good choice for a server that needs a limited range of drivers and is exposed to the internet. A modular kernel is more suited to a desktop or laptop machine that is more likely to have all sorts of peripheral devices plugged into it.

An initrd (initial ramdisk) is needed for the one-size-fits-all nature of a general purpose distro. As I mentioned earlier, certain items, such as drivers for your disk controller, cannot be compiled as modules because modules are not available until after your root filesystem has been mounted. But if every possible permutation were compiled into the kernel, it would be huge. So the modules are loaded into a ramdisk that the system initially mounts as its root filesystem. The startup script in this ramdisk then loads the modules that are needed, mounts the real root filesystem and passes control to it.

If you are building your own kernel, all of this is unnecessary - you can build the drivers you need into the kernel (you only need one disk controller and one filesystem) and leave out the other 99% of options. The only time you should need an initrd with a homemade kernel is if you want to do something clever like running your root filesystem from an LVM volume, or if you want a pretty splash screen at boot.

Back to the task in hand. We used make menuconfig to configure the kernel this time. That has the advantage of not needing X so you can use it on just about any machine, even remotely over SSH. But if you prefer, there are a couple of graphical equivalents: make xconfig and make gconfig. The first uses a Qt GUI while the second has a GTK interface. They both use a multi-pane window with one pane showing the help for the currently selected item - a useful feature when browsing the kernel to see what you can do. The Qt alternative also has a search option, but it is not as useful as the menuconfig search option, which shows you where an option is and what else you need to enable. You have three choices here, but there is no clearly superior choice, so try them all.

Use 'make gconfig' for a GTK-based configurator if you'd like something more mouse friendly.

What if you want to use kernel source from a different place? Good question. Let's say support for your hardware has only been added to the latest release candidate. You would download the latest source code tarball from www.kernel.org, unpack it to /usr/src, change the linux symlink as previously and copy the .config file from your previous kernel build to this directory.

Now you see why we needed to start with the kernel source for your existing kernel. Although you are working with a different version, most of the settings will need to stay the same. There will be some new settings, though, so how do you find and configure those? There's a shortcut for this. First, cd to /usr/src/linux and run

make oldconfig

It will run through your config file and prompt you for any new options not previously set. For each option you will get the usual Y/M/N/? choice. If in doubt press ? to see what each one does. Once you have done this, you may run make menuconfig/xconfig to tweak some of the settings before running make all modules_install install to build and install the kernel as before.
There is one potential problem I should alert you to when building your own kernel from the Kernel.org sources: most distros patch the kernel to a greater or lesser extent for their own uses. Running a vanilla kernel may mean that some things don't work as they should because the patches that the distro expects are no longer there. Slackware users don't have to worry about this, but if you use any other distro you should be aware of the possibility.

Clean up

There are a couple of ways to clean up after yourself, especially when making substantial changes to the configuration. First, make clean removes all compiled files from the kernel tree, resetting it to almost the state it was in before you began compiling. For a more thorough clear-out, use make mrproper, which also cleans out any configuration files. You may want to backup .config before running this.

Patching the kernel

We are nearly finished, and we think we have covered most of the reasons for compiling your own kernel that I gave at the start: reducing size, enabling features and using a newer kernel. But what about patching a kernel? No, don't run away, come back! It's really not that hard. Assuming you have downloaded the correct patch for your kernel, in this example the real time patch for kernel 2.6.33, apply it as follows:

Patches are normally compressed with gzip, but use bunzip2 if yours is compressed with bzip2. You can skip the uncompressing stage by replacing the last two lines with this (use bzcat for a bzip2-compressed patch):

zcat patch-2.6.33-rt7.gz | patch -p1

You should see a list of the files patched and, hopefully, no errors. Errors usually mean you are not using the right patch file, which must match your kernel version. Once you have applied the patch, run make menuconfig/xconfig/oldconfig to set up the new options, then do make all modules_install install. If the patch fails, you may need to alter the -p value. If you look near the top of the patch file, you'll see something like

This shows the name of the file that will be patched with the data that follows. The filename is relative to the current directory. The -p option for patch specifies a number of leading directories (strictly speaking, directory slashes) to remove. We are already in the linux-2.6.33 directory, so -p1 removes this information and looks for arch/i386/lib/usercopy.c. If we had been in the /usr/src directory, we would have needed -p0. Applying the patch from within /usr/src/linux is usually the safest option.

This all might seem rather fiddly, but getting the right -p value is often the hardest part of patching files. There's also a --dry-run option, which you may want to use first. This checks that the patches will apply without making them do so.

Applying a single patch to the kernel tree in this way is quite simple. But problems can arise when you want to apply multiple patches, as they may want to patch the same files as each other. In this case the order in which you apply patches becomes important. Once you start applying more than one patch, you have a number of options. You could spend time searching Google, or reading messages on the Linux Kernel Mailing List, or doing whatever else is needed to get all the patches that you want to apply to cooperate nicely. Or you could apply a patch collection. These collections add several features and enhancements with a single patch command, and there are many of them around, ranging from the well-respected and stable to the downright unstable, use-at-your-own-risk variety.

Third party compilation

Even if you don't want to roll your own kernel, there is a time when you might need the kernel source present in /usr/src/linux. If you want to install anything that adds its own kernel modules, it will need access to the kernel source and a compiler to build those modules. Typical examples of this are the Nvidia graphics card drivers and the VMware emulation platform. Both of these need kernel modules for their own code to communicate with the kernel. They offer a range of pre-compiled modules for popular distros and kernel versions, but if your system is not on the list, or you have upgraded, their installers will need be able to build new modules.

It also follows that when you update your kernel, and this includes recompiling the same version, you then need to reinstall any packages that installed their own modules.

Your comments

Bold

Bold move, encouraging people to customize their kernels nowadays - particularly the way updating the system will fsck your setup on Debian-based distributions, for instance.

Compiling on Ubuntu

Dan Dart (not verified) - March 12, 2010 @ 6:16pm

To compile on Ubuntu you need to install development packages thus:

apt-get install build-essential libncurses5-dev

The last package enables compilation of menuconfig.

Don't forget...

Dan Dart (not verified) - March 12, 2010 @ 6:20pm

Before make menuconfig udr make mrproper to clean out all unneccesary remaining object files you might have lying around. It's a joke: Mr. Proper is a major cleaning product in Europe. In the US it's known as Mr. Clean and in the UK as Flash.

And, you don't need to specify "make all". "make" will do the trick. If you don't specify what make rule you want to use, it will assume "all".

i don't think another compilation guide is needed

marines (not verified) - March 12, 2010 @ 8:45pm

there is a lot of such tutorials. better idea is to guide how to configure kernel which is more important thing.

Be careful

Anonymous Penguin (not verified) - March 13, 2010 @ 10:49am

Compiling a kernel can, in my personal experience, lead to many pitfalls. I wonder if there is a guide somewhere explains what every single option is and how it works. There are many options that are available and some rely on others to operate correctly (or even at all) and there have been times when I have had to re-compile the kernel to fix a silly mistake because of my ignorance. If you can do it with confidence, I totally agree, you can make great savings, but do it with care otherwise you could spend many hours trying to understand and resolve a very complex problem. Good luck

More automatism! (*)

Grateful Cat (not verified) - March 13, 2010 @ 12:54pm

A week ago, give it or take it, I made a comment about compiling -- namely, whether is there an option to select different schedulers.

I also mentioned the problem you (the author) describe when referring to Murphy's law about drivers not present in default distro kernels.

But the problem is way more serious.

I once had the great pleasure to witness the level of completeness Mandriva (then Mandrake) had, as it correctly detected and enabled a smartcard drive. It was ver impressive (to me!) to see that standard kernel without any customizations detect a Castle-something reader and make it work properly.

Now, what do we need to have this in all systems? Yeah, I know about dmesg, lspci, vendor codes and the likes -- but I'd really like to see an advanced hardware detection (which I don't know how to implement) recognize every hardware Linux can accept and propose/save some configuration.

An automatic install could then use such config file to download additional needed drivers.

There are some utilities for hardware detection -- like e.g. kudzu -- which are used for automatic system configuration.

My question is (and I bet it does not happen): does any distro automatically d/ls and compiles new drivers into the kernel? (aside from possibly Gentoo and LFS, which I don't know)

(*) Neither automatism nor automaticity are recognized by Google, though they are in M-W. 8-/

RE: Be careful

Anonymous Penguin44 (not verified) - March 13, 2010 @ 5:38pm

On a kernel up-grade, you use the default config options, (those for your system), using the default is less of a risk. You choose that option over a manual setup; because the total options for a given kernel is something like 2000+ and to doc every one of them in detail for every system/hardware would be worthless to someone with little knowledge to start with. It is a good idea to use the default for new kernel installs, and then work from there to get everything right.

> Are there easier ways to

Grateful Cat (not verified) - March 13, 2010 @ 10:49pm

> Are there easier ways to get introduced to this, still very interesting, part of using Linux? I am not mentally challenged nor do I have grades that approach zero, but I am just a user (not a guru or expert) that is interested in learning. Not the hard way. Like every good first time, as mentioned in your piece, should be relaxed and easy...

Get that old machine no one wants anymore (an old notebook would be ok) and start experimenting. I used to compile kernels whenever I changed the distro (or version).

Not particularly difficult; instructions are very clear and the commands simple. That is, if you don't mess with any option.

Some options back then were also totally nobrainers like:
- Will you use your machine as a router? Usually, no.
- Do you need IPV6? Back then, no; today, I wonder...

There are also options about hardware you don't have (nobrainer) and things you might want to use (sometimes it's good to kept some possibilities open).

If you're dealing with a test machine, there's a lot to learn and not much to lose.

I prefer to make a package with compiled kernel

Yarick (not verified) - March 14, 2010 @ 12:56pm

For debian, as it was said above, I find make-kpkg as the best solution.

For RPM-based distros I use 'make rpm'.

It makes installation/deinstallation of different kernel versions much easier. Also it makes visible, what is installed in the system, on the package manager level.

Perhaps you should take the

Anonymous Penguin (not verified) - March 14, 2010 @ 1:59pm

Perhaps you should take the time to look at the README in the kernel source. Specifically the part where it mentions NOT using /usr/src as your build directory. This is a less than stellar howto with some downright inaccurate info.

BUILD directory for the kernel

Anonymous Penguin (not verified) - March 14, 2010 @ 4:47pm

Quote from the Kernel README:

When compiling the kernel all output files will per default be
stored together with the kernel source code.
Using the option "make O=output/dir" allow you to specify an alternate
place for the output files (including .config).
Example:
kernel source code: /usr/src/linux-2.6.N
build directory: /home/name/build/kernel

To configure and build the kernel use:
cd /usr/src/linux-2.6.N
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install

Please note: If the 'O=output/dir' option is used then it must be
used for all invocations of make.

Yay

bananaoomarang (not verified) - March 14, 2010 @ 7:05pm

couldn't get it to work without a ramdisk. Whatever I tried to compile directly into the kernel.

packagelist for openSUSE

Anonymous Penguin (not verified) - March 17, 2010 @ 4:29pm

if you want to do this on opensuse 11.2 you need to install:
-ncurses-devel
-gcc
-make
-kernel-source

excellent

lostson (not verified) - March 19, 2010 @ 2:53am

everyone should build and hack their own kernels, i have always enjoyed building my own. Excellent artice thank you.

Auto Update

D'Artagnan Palmer (not verified) - April 1, 2010 @ 12:13am

I used to customize my kernel years ago when I fiddled with Red Hat (before Fedora).

I wonder though, in this day of frequent security updates, will using a custom (options, not added code) kernel interfere with auto update giving you the newest kernel?

I think it important that auto update _can_ replace your custom kern with its up to date one. Better secure than custom. Besides, you can re-customize the new one too.

You couldn't reuse your config/choices though, could you?

This and the Kernel Hacking article are good articles.

I'm trying to compile a

Anonymous Penguin (not verified) - September 17, 2010 @ 2:28pm

I'm trying to compile a custom kernel with patches and some modules loaded - however I'm trying to compile it for another system (specifically an O2 joggler here: jogglerwiki.info).

Is it possible to do this? Or will I need to compile it on the hardware I actually intend to use it on?

1 - Search Supports if disconnected from a server, search for a standard installation “OpenVPN client”
spend time for installing downloaded configs to the program.
Troubleshoot the upgraded system for a stable connection to the VPN.
Access to all servers for just 9 EURO.
DoubleVPN, OPENVPN and PPTP VPN - Access to 21 servers in 15 countries!
Subscribe to All Servers of Our Service for 9 Euro; 3 months = 20 Euro; 6 months = 35 Euro; 1 year = 55 Euro.

2 - Unique “VPN Client” is easy to install on all kinds of Operating Systems: MAC / Windows / Linux!!!
Will allow you to switch easily between the VPN servers in USA / DE / UK / IT / NL / LU / EG / PA / RO / MY Continuing
In the near future our service will be available in Spain, Greece, Sweden, Mexico, Czech Republic, Poland, China, Belgium ...
Types of VPN connections included in a single subscription - DoubleVPN and OpenVPN.

3 - The program features an easy configuration of a VPN connection to your Internet: -automatically Block Internet Connection when Disconnected from a VPN.
- Automatic connection to the VPN when you turn on the Internet.

1 - Search Supports if disconnected from a server, search for a standard installation “OpenVPN client”
spend time for installing downloaded configs to the program.
Troubleshoot the upgraded system for a stable connection to the VPN.
Access to all servers for just 9 EURO.
DoubleVPN, OPENVPN and PPTP VPN - Access to 21 servers in 15 countries!
Subscribe to All Servers of Our Service for 9 Euro; 3 months = 20 Euro; 6 months = 35 Euro; 1 year = 55 Euro.

2 - Unique “VPN Client” is easy to install on all kinds of Operating Systems: MAC / Windows / Linux!!!
Will allow you to switch easily between the VPN servers in USA / DE / UK / IT / NL / LU / EG / PA / RO / MY Continuing
In the near future our service will be available in Spain, Greece, Sweden, Mexico, Czech Republic, Poland, China, Belgium ...
Types of VPN connections included in a single subscription - DoubleVPN and OpenVPN.

3 - The program features an easy configuration of a VPN connection to your Internet: -automatically Block Internet Connection when Disconnected from a VPN.
- Automatic connection to the VPN when you turn on the Internet.