Lesson 4: Configuring and building your first kernel

Printer-friendly versionPrinter-friendly version

This is the first major lesson you've been working towards -- configuring, building and rebooting a new Linux kernel. And assuming you've done everything in the previous lessons, there's only one other thing you should be prepared to do. You should be familiar with rebooting your system and, in particular, stopping in the GRUB menu to select the particular kernel you want to boot.

If you've never done that before, now would be a good time to make sure you're comfortable with it.

Working with your kernel tree

Assuming you have your kernel source tree (and if you cloned the Git repository, it will be a very up-to-date tree, which is exactly what we want), you should cd to the top level of that directory, which is where all subsequent kernel configuration and build commands will be run.

As you're introduced to more and more make commands to do what you need, keep in mind that all of these make commands must be run from the top of your source tree; it's actually a common mistake to run those commands from a subdirectory.

One more thing -- there are a number of very sophisticated make targets in the kernel but we're going to restrict our usage in this lesson to only what we need. The more advanced targets will be covered in a future lesson.

Cleaning your source tree

Once you start building kernels, it's common to "clean" your source tree in between builds to make sure you don't run into subtle conflicts between builds. As you get more used to configuring and building kernels, you'll realize when this is necessary and when it isn't, but for now, to clean your source tree totally, run:

$ make distclean

Feel free to do that now even though, if this is a freshly-cloned tree, there's nothing to clean. But run that anyway, it won't do any harm and shouldn't take long at all.

Manual kernel configuration

While this is probably not how you're going to start, you can do a complete manual configuration of your kernel tree with the command:

$ make menuconfig

This dumps you into a curses-based configuration menu, at which point you can move around the menu tree of options and select and deselect kernel options at will. Of course, if you have no idea what you're looking at yet, that's not going to do you much good. So feel free to try that, but just look around and, when you're done, exit without saving anything.

oldconfig kernel configuration

Even if you're entirely new to working with the kernel, you're still going to have to define some kernel configuration as the basis for your build, but where do you get that first configuration?

Quite simply, what you want is a configuration that has a good chance of working with your current system, and the best choice for that is, unsurprisingly, whatever configuration was used for the kernel that is already running. And you already know where to get that, so just identify your current kernel version and copy the appropriate config file from the /boot directory into a file named .config at the top of your kernel source tree:

$ cp /boot/config-[something] .config

But that's not quite everything.

If your currently running kernel is somewhat older than your source tree, it's entirely possible that your source tree has new features that aren't even mentioned in that older config file. And the way to fix that is, after you copy the older config file, to run the command:

$ make oldconfig

What that does is synchronize the config file with the source tree and, everywhere there's a new feature that's not addressed by the older config file, the process will stop and ask you what to do. And that's going to get tedious, so there are a couple of solutions.

The first is to notice that you're probably safe choosing the default choice at each step, so you just need to keep pressing ENTER until the configuration is done. Or just keep your finger on the ENTER key until it's over; that will work, too.

A slightly cleaner way is to run the yes command with two single quotes as arguments, and pipe that into the make command; that effectively does exactly the same thing:

$ yes '' | make oldconfig  [2 single quotes, no space between]

Regardless of how you do it, when you're finished, what you will have is an updated configuration file named .config appropriate for your source tree. And now it's time to build.

(SIDE NOTE: In case you hadn't noticed, your configuration is stored in the file named .config, which is a simple text file that you can read or print if you wish. Take a look at it to see how the file keeps track of which options have been selected for the upcoming build.)

"Naming" your new kernel before you build it

It might have occurred to you by this point that you're free to configure and build numerous kernels that differ every so slightly and you're going to need a way to tell them apart. All you need to do is, before starting a build, manually edit the top-level Makefile and notice the first several lines:

EXTRAVERSION = -rc7      <-- there
NAME = Saber-toothed Squirrel

For each new kernel, if all of the official version numbers are going to be the same, you have the right to change the value of EXTRAVERSION to whatever meaningful string you want, and you'll be able to select which kernel you want to boot based on that value. So take a minute, edit the Makefile, and assign some short, arbitrary value to that variable. You'll see where it shows up later.

And now, the moment we've all been waiting for ...

The build

At this point, if you're happy with your configuration, just:

$ make

and go away until it's done.

If you want to speed things up, you can take advantage of make's inherent parallelism and run it specifying double the number of cores your machine has; since I have a quad-core, I would use:

$ make -j8

"Installing" your new kernel and modules

If everything has worked properly so far, you're now ready to "install" everything you've built into the official system directories and here's where things change just a little bit.

Until now, you've been able to do everything as a regular user -- the downloading, the configuration, the building. But for the next step, you need to have root privilege so you need to do whatever it takes to run the next few commands as root. On my Ubuntu system, I'll be using sudo, of course. And what exactly are we about to do?

Installation will involve the following general steps:

  • Copying a number of your build-generated files into /boot,
  • Creating and populating a new directory of modules for this kernel under /lib/modules, and
  • Updating your (probably GRUB) boot loader to recognize the new kernel so you can select it at boot time.

On a modern Ubuntu system, all of the above can be done by running the following two commands:

$ sudo make modules_install
$ sudo make install

after which you should check that the appropriate content has been installed in the appropriate locations. Don't go any further until you can confirm that that's happened.

Note that the exact instructions might differ from distro to distro, so it's up to you to figure out precisely what it's going to take.

Deep breath and ... reboot

At this point, if you're feeling confident, you can reboot your system and do whatever it takes to stop in the GRUB menu so you can choose to boot your new kernel. On most systems, that's done with the SHIFT key. And if that does the trick, select your new kernel and let it boot. If that works, once the system comes up, you should be able to confirm that you're running your new kernel with:

$ uname -a

If, sadly, something went wrong or the kernel doesn't boot, you can always reboot under the original, working kernel, so there's never any reason to panic.

Seriously, deep breath time

If you're new to building and booting kernels, then this actually represents a major accomplishment so you should take some time and play with everything that's been covered so far. In particular, if you notice any oddities in the lessons, leave a comment, since it's important that what's presented here work properly for beginners.

And if things are looking good so far, it's time for ...


  1. Obviously, your first exercise is simply to follow exactly the recipe above to get a single new, bootable kernel. Once you have that, it's time to test some variations.

  2. Build a second kernel identical to the first, changing only the EXTRAVERSION value in the Makefile to verify that you can in fact build and install more than one kernel. However, when you install the modules, do it slightly differently:

    $ sudo make INSTALL_MOD_STRIP=1 modules_install

    The difference here is that the modules will be "stripped" before being installed under /lib/modules. Once that's done, see how much space you saved. (It should be quite a lot and, in fact, depending on the size of your root filesystem, you might need to strip the modules to avoid running out of space.)

  3. If you're feeling ambitious, build and install a third kernel, but configure it first by removing all kernel features you're fairly sure you don't need. The default configuration for most distros is loaded with all sorts of functionality that you probably don't need, so experiment with how much you can deselect and still have a perfectly viable kernel for your development host.

  4. Finally, "uninstall" one of your new kernels using the fairly obvious manual technique. In our case, just delete all of the related files under /boot and the corresponding /lib/modules subdirectory, then update your bootloader configuration file to have it "forget" about the now-deleted kernel.

    On Ubuntu, that should require:

    $ sudo update-grub

    then reboot to make sure the kernel you just deleted is no longer listed as a boot option.

  5. (SUPER AMBITIOUS) If someone wants to try all of this in something like VirtualBox, give it a shot and report back how it goes.


'make' is missing

In '"Installing" your new kernel and modules' chapter the second command should be 'sudo make install'. 'make' is missing in the text.

Yup, you're right.


Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br> <pre> <h1> <h2> <h3> <h4>
  • Lines and paragraphs break automatically.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.