I Need to Build a Custom Kernel

Created by RalphAngenendt. 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 sources and the other is to build a mainline kernel using sources obtained from The Linux Kernel Archive.

This tutorial will cover the building of a kernel from the CentOS sources with your own options or modifications. It is written for CentOS-7.

(If you wish to build a mainline kernel, do not follow How To Compile A Kernel. That site is not endorsed, as it details building as root which is unsafe and flawed in its approach. See Building Source RPM as non-root under CentOS for the detailed reasoning. A good reference for building a mainline kernel is the book 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 maintenance.

NOTE: If you would like to see a real world example of a custom kernel, get one of the srpm packages for the centosplus kernel. For example, you can find one for CentOS-7 here or for CentOS-6 here.

1. Build preparations

To be able to perform a successful kernel build, you will need to install the following packages:

Whist running the above yum commands note if there are any exclude references. If there are any 'exclude' lines referring to the kernel and related packages in the yum configuration files, they will also need to be removed. One should understand that while the CentOS project does not endorse using such excludes, some vendors do not permit user modified kernels to run in their supported environment. For more details on this topic, see Section 3, Broken Virtual Server CentOS wiki article. Note that it is always wise to have a current and tested backup of any content which you are not willing to lose.

If you have any kernel patches to add, copy them to your ~/rpmbuild/SOURCES/ directory now.

2. Configuring the kernel

If you you do not intend to modify the distributed kernel configuration file you may omit this section (CentOS-7), or you need to perform the equivalent of the final step (CentOS-6):

[user@host] $ cp ~/rpmbuild/BUILD/kernel-*/linux-*/configs/* ~/rpmbuild/SOURCES/

Change directory to ~/rpmbuild/BUILD/kernel-*/linux-*/ and copy into this directory, as .config, either the current configuration file from the configs/ directory or the currently running kernel's configuration file, from the /boot/ directory.

See the example below:

[user@host]$ cd ~/rpmbuild/BUILD/kernel-*/linux-*/

Either -

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

(Replace "3.10.0" with "2.6.32" for CentOS-6.)

- or -

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

Note: The characters around uname -m or uname -r are 'backticks', not apostrophes.

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 changes.

If you have installed the full kernel source to build a kernel module, you should stop at this point. Now please refer to the Build Your Own Kernel Modules tutorial.

Next, add a line that contains the commented out equivalent of the hardware platform to the top of the configuration file (equivalent to the output returned by a uname -i command) just before you copy it back to the configs/ directory. This will be x86_64 for the 64-bit architecture. (For CentOS-6 it could also be i386 for the 32-bit architecture.) It needs to be commented out with a # and must be the first line of the file. Note that there must be a space between the hash symbol and the hardware platform descriptor.

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

# x86_64

or, possibly, for CentOS-6:

# i386

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-3.10.0-`uname -m`.config

Note: The characters around uname -m are 'backticks', not apostrophes.

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. The kernel ABI

One feature of the CentOS kernel is that its ABI will be preserved for the entire life of the product and an advantage of having a consistent ABI is that external kernel modules can be built which are independent of the kernel version -- hence they do not need to be rebuilt for each new kernel released. This is the basis of the kABI tracking kmod package -- to provide updated device drivers and other file system support, for example.

To maintain this ABI consistency, the original kernel's ABI was recorded and stored in a file. This file is used during the kABI checking step for each new kernel being built. If the new kernel has been configured or modified in such a way that it is at variance with the published ABI, the build will fail with a message indicating that kABI breakage has occurred. The kernel builder will then have two choices: (a) re-configure the new kernel so that it does agree with the published ABI and, hence, continue to enjoy the benefits that a consistent ABI provides or (b) disable kABI checking during the build process. Of the two choices, the former is desired but, just occasionally, the latter is the only way to proceed.

Disabling the kernel ABI checking is a simple process of supplying a flag and its argument on the rpmbuild command line:

--without kabichk

4. Modifying the kernel specification file

The kernel specification file should now be modified.

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

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

At line 8, the definition of buildid is commented out. (At line 18, for CentOS-6.)

This must be uncommented and given a value to avoid a conflict with your currently installed kernel. Change the line in a similar manner to the example below:

%define buildid .your_identifier

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

If you have any patches to apply, you need to make reference to them in two places. If you do not have any patches to apply, then just proceed to the line below that reads "End of the patch section."

Firstly, locate a line that reads "# empty final patch to facilitate testing of kernel patches". (For CentOS-6, locate a line that reads "# empty final patch file to facilitate testing of kernel patches".) Just after that line 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

Secondly, locate a line that reads, "ApplyOptionalPatch linux-kernel-test.patch". Just before that line, add a line to apply your patch. For example:

ApplyOptionalPatch my-custom-kernel.patch

End of the patch section.

For CentOS-6 only, locate a line that reads "# Drop some necessary files from the source dir into the buildroot". Replace the next line:

cp $RPM_SOURCE_DIR/config-* .


cp $RPM_SOURCE_DIR/kernel-*.config .

For CentOS-6 only, locate the following line and comment it out:

#make -f %{SOURCE20} VERSION=%{version} configs

5. Building the new kernel

Start the build:

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

Note: The characters around uname -m are 'backticks', not apostrophes.

You can add some useful options to the rpmbuild command by using the --with and/or --without flags and associated arguments. The main options to note are:

--with baseonly
--without up
--without debug
--without debuginfo
--without fips
--without kabichk

For example, to build just the base kernel packages use:

--with baseonly --without debug --without debuginfo

6. Installing the new kernel

When the build completes, your custom kernel rpm files will be found in the user's ~/rpmbuild/RPMS/`uname -m`/ directory. Install them as root, either by using the 'yum' command or the 'rpm' command.

Note: The characters around uname -m or uname -r are 'backticks', not apostrophes.

For example, become root (see How to become root) and cd to the ~user/rpmbuild/RPMS/`uname -m`/ directory. Then execute the following command:

To install all kernel-* packages, run:

[root@host]# yum localinstall kernel-*.rpm

Or, by using the rpm command:

[root@host]# rpm -ivh kernel-*.rpm

When installing the kernel-* packages using the rpm command, you should note that 'kernel' and 'kernel-devel' must be installed, not updated, by using an rpm -ivh command. Note: If you have built a kernel version that is older than a currently installed version you will also have to use the --oldpackage flag with the rpm command.

UNDER NO CIRCUMSTANCES use an 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.

The packages other than 'kernel' and 'kernel-devel' need to be installed (updated) with an rpm -Uvh command. Please note the difference in the flag between -i (install) and -U (update).

HowTos/Custom Kernel (last edited 2017-08-06 23:33:49 by AkemiYagi)