I Need to Build a Custom Kernel

Currently maintained by: AlanBartlett and AkemiYagi

There are two ways to build a custom kernel for CentOS. One is to build a kernel with custom options from the CentOS source rpm and the other is to build a vanilla kernel using sources available from The Linux Kernel Archive.

This tutorial will cover the building a kernel from the CentOS source rpm with your own options or modifications. It is written primarily for CentOS-5. Look out for the <!> sign for notes regarding the building of other versions of CentOS kernels.

(If you wish to build a vanilla kernel, see Building Source RPM as non-root under CentOS. Do not follow How To Compile A Kernel. This site is not endorsed, as it builds as root, which is unsafe and is basically flawed in its approach. A good reference is Linux Kernel in a Nutshell.)

These actions are for your own personal use. Custom kernels are not supported by the development team as they have no control over your build environment, the options chosen, etc. If you choose to build your own kernel, you will be responsible for continuing to maintain it for security updates, new releases, the second coming of $DEITY and any other possible scenario which may warrant such maintainance.


1. Build preparation

You're going to need a few packages to build a kernel properly.

If you have any kernel patches to add, copy them to the SOURCES directory now.

2. Configuring your kernel

If you are not modifying the kernel configuration, you can omit this section.

With the buildroot correctly set up, it's time to modify the kernel configuration. Change directory to ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.`uname -m`/ and copy either the appropriate type of configuration file (base, xen; if 32-bit architecture, PAE (for CentOS-5) or base, smp, xenU; if 32-bit architecture, hugemen; if 64-bit architecture, largesmp (for CentOS-4)) from the ./configs/ directory or that of the currently running kernel from /boot/config-`uname -r` to the .config file in this directory.

See the example below ( <!> Replace 2.6.18 with 2.6.9 throughout the rest of this tutorial, if building a CentOS-4 kernel.):

[user@host]$ cd ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.`uname -m`
[user@host]$ cp configs/kernel-2.6.18-`uname -m`[-type].config .config

- or -

[user@host]$ cp /boot/config-`uname -r` .config

First run make oldconfig. Now you should run either make menuconfig, make gconfig or make xconfig to customize the kernel configuration. Once complete, remember to save your configuration changes.

If you have installed the full kernel source to build a kernel module, you can stop at this point. Please now refer to How to Build Kernel Modules.

Next, add a line that contains the Hardware Platform (equivalent to uname -i) to the top of the .config file just before you copy it back to the configs/ directory. This will either be i386 for the 32-bit architecture or x86_64 for the 64-bit architecture. It needs to be commented out with a # and must be the first line of the file. ( <!> This step is not required for CentOS-4 kernels.)

Add, as the first line of the .config file, either:

# i386

- or -

# x86_64

Copy the .config file back to the configs/ directory. This is basically the opposite of the earlier copy command:

[user@host]$ cp .config configs/kernel-2.6.18-`uname -m`[-type].config

The final step is to copy the entire contents of the configs/ directory to the ~/rpmbuild/SOURCES/ directory.

[user@host]$ cp configs/* ~/rpmbuild/SOURCES

3. Modifying the kernel spec file

Now you will need to modify the kernel spec file.

The line numbers mentioned in this section relate to the current CentOS-5 kernel specification file only.

[user@host]$ cd ~/rpmbuild/SPECS
[user@host SPECS]$ cp kernel-2.6.spec kernel-2.6.spec.distro
[user@host SPECS]$ vi kernel-2.6.spec

<!> The following four changes apply for kernels >= 2.6.18-53.el5 only.

At line 23, change:

%define with_debug     %{?_without_debug:     0} %{!?_without_debug:     1}

to:

%define with_debug     0

At line 29, change:

%define with_debuginfo %{?_without_debuginfo: 0} %{!?_without_debuginfo: 1}

to:

%define with_debuginfo 0

At line 32, change:

%define with_kabichk   %{?_without_kabichk:   0} %{?!_without_kabichk:   1}

to:

%define with_kabichk  0

<!> The above change disables the kABI (kernel Application Binary Interface) checking and, therefore, is not necessary if you know that your customization will not result in a kernel that will be at variance with the published kABI. Otherwise, if kABI breakage occurs, the build process will fail at a very late stage.

At line 69, the definition of buildid is commented out. This must be uncommented and given a value to avoid a conflict with your currently installed kernel. Change the line in similar manner to the example below:

%define buildid .your_identifier

There should be no space between the "%" and the word "define".

Starting at line 4828, there are 26 lines of code that have to be commented out. This block of code begins with #if a rhel kernel, apply the rhel config options. Comment out these lines to build customised CentOS-5 kernels ( <!> This step is not required to build customised CentOS-4 kernels.):

#if a rhel kernel, apply the rhel config options
%if 0%{?rhel}
  for i in %{all_arch_configs}
  do
    mv $i $i.tmp
    $RPM_SOURCE_DIR/merge.pl $RPM_SOURCE_DIR/config-rhel-generic $i.tmp > $i
    rm $i.tmp
  done
%ifarch ppc64 noarch
  #CONFIG_FB_MATROX is disabled for rhel generic but needed for ppc64 rhel
  for i in kernel-%{kversion}-ppc64.config
  do
    mv $i $i.tmp
    $RPM_SOURCE_DIR/merge.pl $RPM_SOURCE_DIR/config-rhel-ppc64-generic $i.tmp > $i
    rm $i.tmp
  done
%endif
%endif
#if a olpc kernel, apply the olpc config options
%if 0%{?olpc}
  for i in %{all_arch_configs}
  do
    mv $i $i.tmp
    $RPM_SOURCE_DIR/merge.pl $RPM_SOURCE_DIR/config-olpc-generic $i.tmp > $i
    rm $i.tmp
  done
%endif

<!> The following two changes apply for kernels >= 2.6.18-92.el5 only.

Comment out line 5073, so that:

    %_sourcedir/kabitool -b . -d %{_tmppath}/kernel-$KernelVer-kabideps -k $KernelVer -w $RPM_BUILD_ROOT/kabi_whitelist

becomes:

#   %_sourcedir/kabitool -b . -d %{_tmppath}/kernel-$KernelVer-kabideps -k $KernelVer -w $RPM_BUILD_ROOT/kabi_whitelist

After line 5107, append a line touch symsets-$KernelVer.tar.gz so that:

    if [ -e $RPM_BUILD_ROOT/Module.kabi ]; then
        mv $RPM_BUILD_ROOT/Module.kabi $RPM_BUILD_ROOT/lib/modules/$KernelVer/build
    fi
    cp symsets-$KernelVer.tar.gz $RPM_BUILD_ROOT/lib/modules/$KernelVer/build

becomes:

    if [ -e $RPM_BUILD_ROOT/Module.kabi ]; then
        mv $RPM_BUILD_ROOT/Module.kabi $RPM_BUILD_ROOT/lib/modules/$KernelVer/build
    fi
    touch symsets-$KernelVer.tar.gz
    cp symsets-$KernelVer.tar.gz $RPM_BUILD_ROOT/lib/modules/$KernelVer/build

Finally, if you have any patches to apply, you need to make reference to them by adding two lines for each patch. After line 2428, which should be near the end of the patch declarations, add your declaration starting with the number 40000, so that your patch is not in any danger of conflicting with the RHEL/CentOS kernel patch space. For example:

Patch40000: my-custom-kernel.patch

After line 4804 add the line to apply your patch. All you need to do is add is the patch number you declared earlier and rpmbuild will automagically apply it for you. For example:

%patch40000 -p1

4. Building your new kernel

Start the build:

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` kernel-2.6.spec 2> build-err.log | tee build-out.log

You can add some useful options to the rpmbuild command using the --with and/or --without flags. ( <!> These options are available for kernels >= 2.6.18-53.el5 only.)

For example:

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` --with baseonly kernel-2.6.spec 2> build-err.log | tee build-out.log

will build only the base kernel & its corresponding kernel-devel rpm files, whilst

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` --with xenonly kernel-2.6.spec 2> build-err.log | tee build-out.log

will build only the xen kernel & its corresponding kernel-xen-devel rpm files and

[user@host SPECS]$ rpmbuild -bb --target=`uname -m` --without up --without xen kernel-2.6.spec 2> build-err.log | tee build-out.log

will build only the PAE kernel & its corresponding kernel-PAE-devel rpm files.

When the build completes, your custom kernel rpm files will be found in the ~/rpmbuild/RPMS/`uname -m`/ directory. Make sure that you install those files, as root, using a rpm -ivh kernel-*.rpm command. Note: If you have built a kernel version that is older than a currently installed version you will have to use the --oldpackage flag with the rpm command.

UNDER NO CIRCUMSTANCES use a rpm -Uvh command to install your kernel as this will update (overwrite) the currently installed version. Hence if you have a problem with your custom kernel, you will not be able to revert to the previous, working, version.

HowTos/Custom Kernel (last edited 2008-11-13 01:04:59 by AlanBartlett)