Lesson 2: Further issues in kernel configuration.

Printer-friendly versionPrinter-friendly version

Kernel configuration and building -- the recap

Recall that, during the course of your very first lesson, you managed to:

  • Download a kernel source tree (in our case using git),
  • Configure it appropriately for your system,
  • Build both the main kernel image and all of the selected loadable modules, and
  • Completely install said kernel and modules to the point where you could reboot and come up under your new kernel.

Recall, as well, that that last kernel "installation" step will, for any Linux distribution, inevitably consist of the following general steps, however they're accomplished:

  • Copy at least the new vmlinuz-* compressed kernel image and a corresponding initrd-* initial ramdisk image into the /boot directory,
  • Copy all of the compiled modules into a new kernel-specific directory under /lib/modules, and
  • Update that distribution's GRUB configuration file to add at least one more stanza for the new kernel so that it's selectable at boot time.

All incredibly straightforward, so what else is there to know about this? I'm glad you asked.

(Aside: I won't always be available to immediately address questions people leave in the comments section so I'm going to reiterate -- use the comments section to chat and ask each other questions. Make this interactive. That's part of the learning process.)

So what's to configure?

Recall that, back in Lesson 1, we cheated a little bit and didn't spend a lot of time actually configuring our new kernel source -- we played it safe and simply used, as a template, an existing config file that came with the initial OS installation.

Once you've done that, though, and you've established that you can build and boot a new kernel based on that, the next obvious step is to invoke one of the kernel configuration targets, say:

$ make menuconfig

and spend some time poking around for obvious reasons -- that's where you'll get a good idea of how many choices you have in building a new kernel. I won't spend much time going over all of the possible choices for kernel feature selection. Again, I'll recommend Greg Kroah-Hartman's excellent book Linux Kernel in a Nutshell. However, I will treat you to one handy feature of the config process.

Occasionally, you'll read advice that says that to build in, for example, the "kexec" feature, you should select the CONFIG_KEXEC config variable, which is terrific if you happen to know where in the murky depths of the configuration menus that variable happens to live.

If you don't though, no problem -- simply start the configuration utility and search for the string by typing:

/kexec     [slash, followed by string of interest, then ENTER]

What you get back is a list of every single kernel option containing that text string, and its location in the menu structure. Very handy indeed. Why you would select that particular feature and what you'd do with it -- well, that's the topic for a future lesson. I'm just showing you how the search feature works.

make targets and pre-defined configurations

In case you hadn't figured it out by now, almost all kernel tree configuration is done through the top-level Makefile by invoking one of its numerous targets, the entire list of which can be displayed with:

$ make help

Perhaps the most useful target for beginners is defconfig (short for "default config") which simply sets your .config to an established set of defaults for your system and architecture. And how can you see these defaults? Simple -- from the top of the kernel source tree, just run:

$ find arch -name "*defconfig"

and you'll see dozens of default config files for all of the kernel's supported architectures. Assuming you're working on an x86-like architecture, you're probably interested only in these:

$ find arch/x86 -name "*defconfig"
arch/x86/configs/x86_64_defconfig   [64-bit version]
arch/x86/configs/i386_defconfig     [32-bit version]
$

In addition, running make help shows you some other rather odd configuration targets:

...
Configuration targets:
  ... 
  randconfig      - New config with random answer to all options
  defconfig       - New config with default answer to all options
  allmodconfig    - New config selecting modules when possible
  allyesconfig    - New config where all options are accepted with yes
  allnoconfig     - New config where all options are answered with no
...

Those targets are certainly a bit unusual, and you might wonder why anyone would configure a kernel so strangely. Actually, those targets have value for stress-testing the build process. It's not enough to verify that the kernel can build for typical configurations; it's good practise to see if those extreme corner cases also build. Feel free to configure your kernel tree with one of them and see if the build actually works.

Building verbosely

If you want more output during the kernel and module compilation stage, running make help shows you how to get that and also how to do static code analysis on the source if you're interested in that sort of thing:

  ...
  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build
  make V=2   [targets] 2 => give reason for rebuild of target
  ...
  make C=1   [targets] Check all c source with $CHECK (sparse by default)
  make C=2   [targets] Force check of all c source with $CHECK

Cleaning up your mess before starting over

If you're simply playing and want to tidy up before trying another configuration and build, there are three clean-type targets:

$ make help
...
Cleaning targets:
  clean           - Remove most generated files but keep the config and
                    enough build support to build external modules
  mrproper        - Remove all generated files + config + various backup files
  distclean       - mrproper + remove editor backup and patch files

That last one, distclean, removes every vestige of any previous configuration or build and should take you back to, literally, the pristine, distribution version of the kernel source. That includes even removing your .config file so don't use that target unless you're serious about cleaning your source tree.

Building in an alternate directory

Until now, all of your configuration and compilation has been done in the same directory as the kernel source itself, which is fine for most people but, in some cases, it's more convenient to preserve the kernel source untouched and have all the configuration output and compilation results generated in a remote directory. No problem.

From the top of the kernel source tree, you can do something resembling the following:

$ mkdir ../build_dir
$ make O=../build_dir menuconfig
$ make O=../build_dir
$ sudo make O=../build_dir modules_install

and so on, and so on. And what's the benefit?

For one thing, it leaves the source unpolluted by all of those output files, which makes it easier if you want to search the tree using something like grep.

For another, it allows you to work with a directory of kernel source for which you have no write access. Perhaps it's a system directory, or in some other user's home directory. As long as you can cd to the top of the source tree and have read access to all of the source, you can generate all of the output elsewhere.

And, finally, this feature lets you work with multiple configurations and builds simultaneously, since you can simply switch from one output directory to another on the fly, using the same kernel source directory as the basis for all of those builds.

There is only one caution, though. Once you initially select an output directory, you must specify that output directory on every subsequent make invocation, but that should simply be obvious. In fact, the last time I checked, you can't use the remote directory feature if your kernel source tree already shows signs of internal configuration. In short, this feature is meant to be used with a pristine kernel source tree.

Generating unique build version numbers

Recall from the first lesson that, if you plan on building and installing your own kernels, you should take care that the version strings that they are stamped and installed with don't clash so that they you end up overwriting an earlier kernel that you wanted to keep. You can display the kernel release string of the running kernel with

$ uname -r
2.6.35-crash+
$

And you might remember that you can modify that "extra version" information by simply editing the content at the top of the kernel Makefile before starting a new configuration:

VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
EXTRAVERSION = -crash    <-- change that part

In fact, there's considerably more to it than that so I'll simply point you at how the configuration and build process generates the release number that will be assigned to the new kernel.

First, there's this incomprehensible excerpt from the Makefile:

# Build the kernel release string
#
# The KERNELRELEASE value built here is stored in the file
# include/config/kernel.release, and is used when executing several
# make targets, such as "make install" or "make modules_install."
#
# The eventual kernel release string consists of the following fields,
# shown in a hierarchical format to show how smaller parts are concatenated
# to form the larger and final value, with values coming from places like
# the Makefile, kernel config options, make command line options and/or
# SCM tag information.
#
#       $(KERNELVERSION)
#         $(VERSION)                    eg, 2
#         $(PATCHLEVEL)                 eg, 6
#         $(SUBLEVEL)                   eg, 18
#         $(EXTRAVERSION)               eg, -rc6
#       $(localver-full)
#         $(localver)
#           localversion*               (files without backups, containing '~')
#           $(CONFIG_LOCALVERSION)      (from kernel config setting)
#         $(LOCALVERSION)               (from make command line, if provided)
#         $(localver-extra)
#           $(scm-identifier)           (unique SCM tag, if one exists)
#             ./scripts/setlocalversion (only with CONFIG_LOCALVERSION_AUTO)
#             .scmversion               (only with CONFIG_LOCALVERSION_AUTO)
#           +                           (only without CONFIG_LOCALVERSION_AUTO
#                                        and without LOCALVERSION= and
#                                        repository is at non-tagged commit)
#
# For kernels without CONFIG_LOCALVERSION_AUTO compiled from an SCM that has
# been revised beyond a tagged commit, `+' is appended to the version string
# when not overridden by using "make LOCALVERSION=".  This indicates that the
# kernel is not a vanilla release version and has been modified.

And if that's not confusing enough, I recommend perusing the code in the utility script scripts/setlocalversion to see how even more can be tacked onto the release string that will be used for your new kernel.

However, to make a long story short, if you want to see what release string will be used:

$ make kernelrelease
2.6.35-crash+
$

at which point you can decide if you need to do any adjustment to avoid release string conflicts.

Configuring for another architecture

While the final topic for this lesson is somewhat beyond the scope of the course, it's worth seeing at least briefly how you would configure your kernel for building on another architecture.

Take a look at the currently-supported architectures:

$ ls arch
alpha  blackfin  h8300    m32r       microblaze  parisc   score  um
arm    cris      ia64     m68k       mips        powerpc  sh     x86
avr32  frv       Kconfig  m68knommu  mn10300     s390     sparc  xtensa
$

and peruse what the configuration process would look like with, for example:

$ make ARCH=blackfin menuconfig

You won't be able to actually build a kernel for any other architecture until you install the appropriate cross-compiler toolchain -- a topic we might very well return to in a future lesson.

So ... where to from here?

We're almost done with establishing the fundamentals we need to start some kernel programming. The last supporting topic we need to cover is the manipulation and examination of loadable kernel modules, which is the topic for the next lesson. And once that's done, starting with lesson four, we'll jump right into writing, compiling and loading our first kernel modules.

And you won't want to miss that.

Comments

A few more ideas

A tutorial or lesson on git with a case study will also help a lot. For instance how will we maintain our own kernel code along with the mainstream and how will we update our code and also submit our code to the mainstream kernel code.

Some work on initrd might also help some of us. Keep up the good work.

Do I really want to cover git?

Possibly, but I want to be careful that I don't pad out the course with material that *some* people would like to see, but that most people wouldn't be interested in and would have no use for.

I'll probably write a short introduction to git for beginners and just make it a free tutorial for anyone, so you get the best of both worlds.

Building in a seperate directory

So, Im catching up here and want to subscribe to the course next week as well.

Everything went fine so far except for building the kernel in a seperate directory. (the error was saying something like "no target for make...."). I really thought I had it right though. What could be the cause there? I'm also happy for a (little) reading-advice about makefiles.

Btw. that error also came up a while ago when I tried to build a hello-world-module against some kernel in a seperate directory.

thanks for this so far. I hope to figure that issue out, then I think I'm prepared to dig into it.

greets!
martin

Building in a remote(?) output directory

It looks like you have two issues here. First, there's simply building a new kernel in an output directory different from the kernel source directory -- I think that's your first issue.

Just follow the directions above *exactly*. You have to run every make command with the "O=" argument -- it sounds like you failed to do that for the configuration step. I've verified that the instructions given above appear to work.

As for the rest of your question, all that is going to be covered in Lesson 6, which I'm writing at the moment, so you just have to be patient and it will all be explained in time. For now, keep things simple and just build against the kernel tree that corresponds to your running kernel.

thanks!

thanks for answering! that command did not work for me:
$ make O=../build_dir make
but make O=... did work.

I would have two little questions: Can I review all the warnings that come up during the build afterwards?

And: Is there a comfortable way to remove an installed kernel except for removing the files manually/by a script?

thanks a lot for this!

Building a new kernel as a package

First, I'm not sure what you're saying about that initial make command. What exactly is the command that worked for you? The one I gave should work just fine, I've used it many times.

Also, the kernel source tree comes with some targets that build a new installable package, such as:

$ make rpm-pkg (for Fedora)
$ make deb-pkg (for Debian/Ubuntu)

so you can install the kernel as a package, and uninstall it later. At least, that's the theory.

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.

We know

We're aware of the time and budget pressures at most companies, normally accompanied by the plaintive cry from management of, "Yes, I know we need training on that topic, but I just can't afford to send my entire team away for three (or four or five) days to get it!" And that's where we come in.

Choices!

The main focus at Crashcourse is to offer a choice of intense, 1-day, hands-on courses on specific topics in Linux and open source. And given that we already have the laptops for the delivery of that training, the idea is to show up early, set up a classroom, then spend the day teaching exactly the topic you're interested in. No travel time, and no wasted classroom time.

Customization

If we don't already have a course that addresses the topic you're interested in, drop us a note and we'll see what we can do -- our content providers can almost certainly put together a course that's precisely what you're after.

The difference

While there are a variety of sources for Linux and open source training, we at Crashcourse are taking a slightly different approach. Our philosophy is simple: exactly the training you want, and no wasted time or travel to get it.