RANDOM FORTUNE:

"What is the robbing of a bank compared to the FOUNDING of a bank?"
          -- Bertold Brecht

Kernel Compiling

One of the things that can really mess up your system is a failed kernel build. But you have just installed your shiny new distro and you really need to tweak it a bit, or maybe you need modular support for a piece of hardware so you can add some options when it is loaded without needing to reboot. Whatever the reasons, let's take a look at the process.

Note that this article does not discuss making an initrd.

Throughout this howto whenever you see $version it means the version of kernel, which you should substitute for the actual version that you are using.

First of all though, there are some differing opinions to where you should put the kernel source. In Slackware by default it is installed to /usr/src, but there is an argument for putting it elsewhere when compiling a custom build. I will stick with /usr/src for now, to keep all my kernel source in the same place. Just be sure not to overwrite any exiting source there that you need to keep.

This argument about where to build it dates back to an old mailing list post by Linus Torvalds in 2000:

http://lkml.indiana.edu/hypermail/linux/kernel/0007.3/0587.html

But wherever you install the source doesn't make much difference to this howto. Adjust the paths as necessary.

Pre-Compile Tasks

Gather all the info you can about your hardware. Some useful commands:

lspci -v(vv)
lsusb -v
dmidecode
lsmod
less /proc/cpuinfo

These will help a lot if you want to take out the generic settings and/or only put in support for your chipset and other hardware.

The Kernel Source

Grab the required kernel source and untar it in your desired working directory. We'll suppose /usr/src for this.

The latest source is available at kernel.org.

Note that you may want to add a custom name to it that you can keep it separate to the stock kernel versions. .e.g. 'linux-custom-$version'. By default the directory will be named linux-$version.

Get a Config

First you need a config to build from. Your currently running kernel config can be found in /proc/config.gz

There are several tools that you can use to reveal the contents:

zless /proc/config.gz
zgrep "SEARCHTERM" /proc/config.gz
zcat /proc/config.gz | grep "SEARCHTERM"

etc.

Note that the configuration option names are always uppercase.

If you are building a very new kernel I would recommend using the configs provided in the k/ directory of the slackware64-current source tree for the closest match to your kernel version (go higher if in doubt):

https://mirrors.slackware.com/slackware/slackware64-current/source/k/kernel-configs

Configuring

cd linux-$version

To use the currently running kernel config as a starting point:

zcat /proc/config.gz > .config

Otherwise simply copy the config file you have to '.config'.


From here you have a few choices:

(You may need to run 'make clean' and 'make prepare' before any of these if you have recompiled a few times. It's usually good practice anyway.)

This will start a curses menu screen where you can search/edit options and find information on each module or setting:

make menuconfig

This will prompt you on the command line for your choice on new settings one by one:

make oldconfig

This wil prompt you for all settings one by one:

make config

There is also 'make xconfig', which does the same as 'make menuconfig', but in an X window.

There are many more build options available. To see them all use 'make help | less'.

Important note:

All drivers for hardware needed to boot the machine must be compiled in and not as modules. Examples of this are the bus and file system drivers needed to read the hard disk drive to boot from.

The Compile

After configuring the next step is to build the kernel.

Note: There is a 'make install' option, but I won't be using that here. I prefer to copy the kernel image and files over manually so there is no accidental clobbering of anything in /boot. However it's necessary to install the modules using the normal install method as it's not possible to do that manually. Well, you could, but it would take you until next Christmas.

make
make modules_install
cp arch/x86/boot/bzImage /boot/vmlinuz-$version
cp System.map /boot/System.map-$version
cp .config /boot/config-$version

Module dependencies need to be updated:

depmod -a $version

Take note of any errors from that last command.

The Boot Loader

It's necessary to update lilo with the new kernel information.

lilo -v

If you have built a new kernel you will need to add an entry for it in /etc/lilo.conf or your grub config file. Make sure you leave your old entry in there as a failsafe.

Here is a lilo example (you will need to set the correct 'root' partition):

# Linux bootable partition config begins
image = /boot/vmlinuz-$version
root = /dev/sda1
label = Linux-$version
read-only
# Linux bootable partition config ends

Note that when slackware kernel packages are installed or upgraded using the pkgtools applications (this goes for slackpkg too) a symlink is made to the kernel as /boot/vmlinuz (the same applies for System.map and the config). So be aware that you need to keep those intact if you want to boot up the stock, existing kernel as a failsafe.

It's worth taking a look in /boot to become familiar with what is there.

If there were no errors from running lilo then continue to the reboot stage.

The Reboot Test

Ok - moment of truth. Reboot the machine, choose your new kernel at the bootloader prompt, and watch the bootup messages. If all goes well then you have a working system and you can have a look through 'dmesg -H' and check for any problems. If all didn't go well, reboot with your old kernel (you left the entry for it in /etc/lilo.conf right?) Now have a good look through your kernel setup to see what you missed. From here on it's a case of rinse and repeat until it all works as expected.

Out of Tree Kernel Modules

If you have any out-tree kernel modules then they will need reinstalling. Typical examples are graphics and network drivers such as nvidia and madwifi.