Where do I find the kernel?
The latest source code for the Linux kernel is kept on kernel.org. You can either download the full source code as a tar ball (not recommended and will take forever to download), or you can check out the code from the read-only git repositories.
What tools do I need?
To build the Linux kernel from source, you need several tools: git, make, gcc, and (optionally) ctags and/or ncurses-dev. The tool packages may be called something else in your Linux distribution, so you may need to search for the package. The ncurses-dev tools are used if you "make menuconfig" or "make nconfig".
Which kernel to build?
If you want to test to see if a bug is fixed then test against the latest stable kernel from kernel.org. If you are brave and your system is backed up the latest release candidate from Linus's tree is a great target. Sometimes the maintainer may want you to use an experimental branch from their own git tree. You should use the git URL they gave you instead of the git URLs below.
If you're doing development for a new feature, or trying to test a bug fix, you should use Linus' tree, or the subsystem maintainer's -next tree. Most subsystem maintainers keep their git trees on kernel.org. When in doubt, use Linus' tree.
If you don't understand what a stable or release candidate kernel is, you should read the KernelDevProcess page.
Downloading the latest stable tree
Find the latest stable kernel by looking for the largest vX.Y.Z values. For example, use the v3.1 tag over the v3.0.46 tag. If v3.1.1 is available, use that instead of v3.1. The kernel tags that end with -rcX are release candidate kernels, not stable kernels.
Downloading the latest -rc tree
Setting up your kernel configuration
Many kernel drivers can be turned on or off, or built as modules. The .config file in the kernel source directory determines which drivers are built. When you download the source tree, it doesn't come with a .config file. You have several options on generating a .config file. The easiest is to duplicate your current config.
Duplicating your current config
If you're trying to see if a bug is fixed, you probably want to duplicate the configuration on your running kernel. That config file is stored somewhere in /boot/. There might be several files that start with config, so you want the one associated with your running kernel. You can find that by running uname -a and finding the config file that ends with your kernel version number. Copy that file into the source directory as .config. Or just run this command:
Making the default config
Making a minimal config
Compiling a kernel from scratch from a distribution configuration can take "forever" because the distros turn on every hardware configuration possible. For people wanting to do kernel development fast, you want to make a minimal configuration. Steve Rostedt uses ktest.pl make_min_config to get a truely minimum config, but it will take a day or two to build. Warning: make sure you have all your USB devices plugged into the system, or you won't get the drivers for them!
Changing your config
Building the kernel
Walk away, get some coffee, lunch, or go read some comics.
Installing the kernel
To install a kernel, you will need to either manually update your GRUB configuration file, or have an installkernel script. This script installs the kernel to /boot/, installs modules to /lib/modules/X.Y.Z/ (where X.Y.Z is something like 3.1.5), and updates file /boot/grub/grub.conf. Fortunately, Ubuntu provides an installkernel script in /sbin/installkernel. The grubby RPM provides it for RPM based systems.
Running your kernel
First, make sure you know how to select a kernel at boot time. If your new kernel is broken, you want a way to boot into your old kernel. The grub bootloader usually presents users with a choice of kernels and you can reboot into a known good kernel if your new compile doesn't work. Some distros use a default grub config that hides that menu. You can usually get the menu to appear by mashing the ESC key during boot after the BIOS display disappears.
Ubuntu: To make the grub menu always appear on boot under Ubuntu, remove the GRUB_HIDDEN_TIMEOUT_QUIET line from /etc/default/grub. You may want to increase the GRUB_DEFAULT timeout from 0 to 15 seconds or more. After you've finished editing the grub file you may need to update your grub file.
Patching your kernel
There are several ways to apply a patch to your kernel. Usually the maintainer will send you a patch as attachment, or inline in the mail. You should either save the file, or copy and paste the patch into a new file.
(Note: the older way of manually patching the kernel with patch -p1 <patchfile does not create any git history, which makes it hard to revert and retry different patches. You will often have to go through several patches with a maintainer to find the right fix for a bug, so having the git history is useful.)
Reverting a patch
If you need to revert several patches, you can use git log to find the commit ID of the first commit before those patches. For instance, say you have applied two patches to the stable tree 3.4.17, and you want to revert those patches. git log will look like this:
$ git log --pretty=oneline --abbrev-commit 8901234 Testing patch 2 1234567 Testing patch 1 5390967 Linux 3.4.17 1f94bd4 drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13 0187c24 x86, mm: Use memblock memory loop instead of e820_RAM a0419ca staging: comedi: amplc_pc236: fix invalid register access during detach
Tips and Tricks
If you have a driver installed as a module, you can recompile just that driver. This saves time, because the kernel build system doesn't have to look for changes across the entire kernel tree or compile any of the built-in code.
Make sure that you understand the consequences of unloading your driver! For instance, if you unload the USB core driver in order to try out changes, your USB mouse and keyboard aren't going to work until the USB core driver is reloaded.
$ lsmod | grep usb usbnet 26596 2 rndis_host,cdc_ether mii 5198 1 usbnet btusb 16575 0 usbhid 44621 1 hid_logitech usbcore 191078 9 xhci_hcd,rndis_host,cdc_ether,usbnet,btusb,uvcvideo,usbhid,ehci_hcd usb_common 1093 1 usbcore
Kernel Rebuild Guide, Kwan Lowe, 2004