Building a custom kernel

Building a Kernel from the source RPM
This document provides instructions for advanced users who want to rebuild the kernel. Note, however, that when building or running any such kernel, one should NOT expect support from the Fedora kernel team, you're pretty much on your own here if something doesn't work as you'd hoped or expected. But hey, you're an advanced user, so you can handle it, right? Anyway, advanced users build custom kernels for a variety of reasons:
 * To apply patches for testing that they either generated or obtained from another source
 * To reconfigure the existing kernel
 * To learn more about the kernel and kernel development

These instructions can also be used for simply preparing the kernel source tree.

Before starting, make sure the system has all the necessary packages installed, including the following:



yum-utils is a default package. To install the other package, use the following command:

su -c 'yum install rpmdevtools yum-utils'

If you plan to use, it will be necessary to install the additional packages:

For Fedora 15, use the following command: su -c 'yum install qt3-devel libXi-devel'

Get the Source
warning: user kojibuilder does not exist - using root warning: group kojibuilder does not exist - using root
 * 1) Prepare a RPM package building environment in your home directory.  Run the following command: rpmdev-setuptree This command creates different directories ,  , and  . Where   is your home directory.
 * 2) Download the   file.  Enable the appropriate source repositories with the   switch. (yumdownloader --enablerepo=repo_to_enable --source kernel) yumdownloader --source kernel
 * 3) Install build dependencies for the kernel source with the   command (root is required to install these packages): su -c 'yum-builddep kernel- .src.rpm'
 * 4) Install   with the following command: rpm -Uvh kernel- .src.rpm This command writes the RPM contents into   and , where   is your home directory.  It is safe to ignore any messages similar to the following:

Prepare the Kernel Source Tree
This step expands all of the source code files for the kernel. This is required to view the code, edit the code, or to generate a patch.

1. Prepare the kernel source tree using the following commands: cd ~/rpmbuild/SPECS rpmbuild -bp --target=$(uname -m) kernel.spec

The kernel source tree is now located in the  directory.

Copy the Source Tree and Generate a Patch
This step is for applying a patch to the kernel source. If a patch is not needed, proceed to "Configure Kernel Options".

Copy the source tree to preserve the original tree while making changes to the

export arch=x86_64 # replace x86_64 with your arch export ver=3.1 # replace 3.1 with your kernel version export fedver=fc16 # replace fc16 with your fedora version cp -r ~/rpmbuild/BUILD/kernel-$ver.$fedver/linux-$ver.$arch ~/rpmbuild/BUILD/kernel-$ver.$fedver.orig cp -al ~/rpmbuild/BUILD/kernel-$ver.$fedver.orig ~/rpmbuild/BUILD/kernel-$ver.$fedver.new

Using vim on FC14, it treated the hard link as a hard link and thus the above technique failed. It was necessary to repeat the original copy used for the .orig directory for the .new directory. Note that this uses twice the space.

Make changes directly to the code in the  source tree, or copy in a modified file. This file might come from a developer who has requested a test, from the upstream kernel sources, or from a different distribution.

After the  source tree is modified, generate a patch. To generate the patch, run  against the entire   and   source trees with the following command:

cd ~/rpmbuild/BUILD diff -uNrp kernel-$ver.$fedver.orig kernel-$ver.$fedver.new > ../SOURCES/linux-$ver.$fedver-mynewpatch.patch

Replace 'linux-$ver.$fedver-mynewpatch.patch' with the desired name for the new patch. On FC14 it was necessary to copy the above patch name to linux-$ver.$fedver-mynewpatch.patch in ~/rpmbuild/SOURCES as well in order for rpmbuild to find it.

Configure Kernel Options
This step is for modifying the options the kernel is configured with. This step is optional. If no configuration changes are needed, proceed to "Prepare Build Files".


 * 1) Change to the kernel source tree directory: cd ~/rpmbuild/BUILD/kernel-$ver.$fedver/linux-$ver.$arch/ If you only want to make minor changes to the default fedora kernel, skip to step 4., and use one of the two configuration tools to edit those minor changes into the default config file.
 * 2) Select the desired configuration file from  . Copy the desired config file to  : cp configs/ .config
 * 3) Run the following command: make oldconfig
 * 4) Then run the following command, selecting and saving the desired kernel options from the text-based UI: make menuconfig
 * 5) * For a graphical UI, instead run: make xconfig
 * 6) Add a new line to the top of the config file that contains the hardware platform the kernel is built for (the output of  ). The line is preceded by a   sign. For example, an x86_64 machine would have the following line added to the top of the config file: # x86_64
 * 7) Copy the config file to  : cp .config ~/rpmbuild/SOURCES/config-`uname -m`-generic

Prepare Build Files
This step makes the necessary changes to the  file. This step is required for building a custom kernel.

1. Change to the  directory:

cd ~/rpmbuild/SPECS

2. Open the  file for editing. 3. Give the kernel a unique name. This is important to ensure the custom kernel is not confused with any released kernel. Add a unique string to the kernel name by changing the 'buildid' line. Optionally, change ".local" to your initials, a bug number, the date or any other unique string.

Change this line:
 * 1) % define buildid .local

To this (note the extra space is removed in addition to the pound sign): %define buildid .

4. If you generated a patch, add the patch to the  file, preferably at the end of all the existing patches and clearly commented.

Patch2220: linux-2.6-cputime-fix-accounting.patch
 * 1) cputime accounting is broken, revert to 2.6.22 version

Patch9999: linux-2.6-samfw-test.patch

The patch then needs to be applied in the patch application section of the spec file. Again, at the end of the existing patch applications and clearly commented.

ApplyPatch linux-2.6-cputime-fix-accounting.patch

ApplyPatch linux-2.6-samfw-test.patch

Build the New Kernel
This step actually generates the kernel RPM files. This step is required for building a custom kernel. For Fedora 10 or 11, for most purposes, it will be simplest to build with firmware included (see the last form below).

Use the  utility to build the new kernel:

rpmbuild -bb --target=`uname -m` kernel.spec
 * To build all kernel flavors:


 * To disable specific kernel flavors from the build (for a faster build):

rpmbuild -bb --without --target=`uname -m` kernel.spec

Valid values for "option" above include,  ,  ,  ,  ,   and. Specifying  strips out some debugging code from the kernels, where specifying   disables the building of the   packages.


 * To specify that only a specific kernel should be built:

rpmbuild -bb --with --target=`uname -m` kernel.spec

Valid values for "option" above include,  , and.


 * For example, to build just the kernel and kernel-devel packages, the command would be:

rpmbuild -bb --with baseonly --without debuginfo --target=`uname -m` kernel.spec


 * To build with firmware included, do:

rpmbuild -bb --with baseonly --with firmware --without debuginfo \ --target=`uname -m` kernel.spec

The build process takes a long time to complete. A lot of messages will be printed to the screen. These messages can be ignored, unless the build ends with an error. If the build completes successfully, the new kernel packages will be located in the  directory.

Following Generic Textbooks
Many of the tutorials, examples, and textbooks about Linux kernel development assume the kernel sources are installed under the  directory. If you make a symbolic link, as shown below, you should be able to use those learning materials with the Fedora packages. Install the appropriate kernel sources, as shown earlier, and then run the following command:

su -c 'ln -s /usr/src/kernels/. - /usr/src/linux'

Enter the  password when prompted.

Install the New Kernel
This step actually installs the new kernel into the running system.

To install the new kernel, use the  command, not the   or   options:

su -c "rpm -ivh --force $HOME/rpmbuild/RPMS/ /kernel- . .rpm"

If you changed the name of your kernel as requested, your firmware and kernel headers won't match. The simplest solution is to build new firmware as described in 'Build the New Kernel', then

su -c "rpm -ivh $HOME/rpmbuild/RPMS/ /kernel- . .rpm \      $HOME/rpmbuild/RPMS/ /kernel-firmware- . .rpm \       $HOME/rpmbuild/RPMS/ /kernel-headers- . .rpm \       $HOME/rpmbuild/RPMS/ /kernel-devel- . .rpm"

These commands will install your kernel in /boot, create a new initramfs to bootstrap your kernel, and automatically add your new kernel to your grub bootloader "menu.lst". At this point, you can reboot to give control to your new kernel.

Building Only Kernel Modules (Out Of Tree Modules)
This section is for users who are only interested in working on a kernel module, and who do not wish to build an entire custom kernel. It is not necessary to download and rebuild the entire kernel in order to build a module. To build a module for the currently running kernel, only the matching  package is required. Run the following command to install the  package using.

su -c 'yum install kernel-devel'

You can build against any kernel version, as long as you have  and   packages installed for that version. The rest of this section assumes we're building for the running kernel; if not, replace  with the desired version number.

As a simple example, to build the  module from , create the following   in the directory containing the   file:

obj-m := foo.o

KDIR := /lib/modules/$(shell uname -r)/build PWD  := $(shell pwd)

default: [TAB]$(MAKE) -C $(KDIR) M=$(PWD) modules [TAB] Denotes a tab character which must come first for makefile lines containing commands.

Then, issue the  command to build the   module.

The above is a helpful local Makefile wrapper invoking kbuild; in general you can simply do things like


 * 1) make -C /lib/modules/`uname -r`/build M=`pwd` modules
 * 2) make -C /lib/modules/`uname -r`/build M=`pwd` clean
 * 3) make -C /lib/modules/`uname -r`/build M=`pwd` modules_install

etc to build those targets.