Supporting Multiple Kernel Versions
I use a Bash script called KernelBuild.sh to compile the kernels and produce the binary distributions. It takes one argument, the name of a kernel source file (without the “.tar.bz2” extension—e.g., ./KernelBuild.sh linux-2.0.36.bphys). It starts by defining a few environment variables:
MY_WORK is my working directory. Here, the kernel sources will be unpacked and the distributions will be built. KernelBuild.sh expects to find all the scripts and tools it needs in the directory $MY_WORK/bin. It will also ensure the correct subdirectory structure exists for building the distributions. The built kernels are installed here, not under the root directory, and the distribution tar file is created at this level. Users can unpack it in the true root directory of their client machines.
MY_SRC is the directory containing the prepared kernel sources. I set this as a separate variable to allow customisation of the compilation scripts in another working directory, without having to copy the sources with them. For example, separate teams who wish to build their own versions of the kernels could set MY_SRC to the source directory in a common repository and use the sources directly from that location.
MY_ROOT is the root directory from which the link is set to the source code of the kernel being compiled. In other words, KernelBuild.sh sets a soft link from $MY_ROOT/linux to point to $MY_WORK/linux-2.0.36.bphys—or whichever version it is compiling. In a normal Linux environment, MY_ROOT would be /usr/src, and the link would be set from /usr/src/linux to the actual source tree. By allowing it to be another directory, it is possible to compile the kernel as a normal user in another directory instead of working as root. You set the link /usr/src/linux to point to $MY_ROOT/linux once, as root. Then you can change the link $MY_ROOT/linux, as the user who compiles the kernels, as often as you wish.
KERNEL_VERSION is simply the input argument.
The MY_* environment variables may be defined externally if you wish, and will not be overridden by the script. KERNEL_VERSION will always be set from the input argument.
KernelBuild.sh does not actually do the work of compiling the kernels. For this, it uses two other scripts, Meanwhile.pl and KernelBuild.cmds. Meanwhile.pl is a Perl script which will execute a Bash script in the background, log all the output and send an e-mail message when it is done.
The real workhorse is KernelBuild.cmds, which can be executed as a stand-alone script, although normally you would use KernelBuild.sh. It unpacks the source code tree, uses KernelConfig.exp to configure it, compiles the uniprocessor version of the kernel, packs it into a binary distribution file, packs the header files into a header-file-distribution, then repeats the process for the SMP version.
KernelConfig.exp determines how a kernel is to be configured, but KernelBuild.cmds determines how it is to be built and installed. The boundaries between the two are a bit blurred because of the way in which SMP support has changed from the 2.0.x series to the 2.2.x series, as mentioned earlier. If you wish to customise the build, it is these two scripts that you will want to change.
KernelBuild.cmds makes use of the fact that anything stored in a file called .name at the top level of the kernel source will be incorporated into the kernel name and can be retrieved later using the commands uname -v or cat /proc/version. I use this to record the kernel version string, including the distinction between uniprocessor and SMP versions. For the 2.2.x series, the Makefile includes this distinction, but for the 2.0.x series it does not. KernelBuild.cmds uses a bit of sed, smoke and mirrors to smooth out the differences.
Finally, the binary and header file distributions are stored in the /dist directory, packed using tar, and compressed with bzip2. The binary distribution contains the kernel image, the System.map and all modules. It also contains a copy of KernelConfig.exp, so in the likely event that this script is updated, you will still have access to the exact version used to compile any particular distribution of the kernel. For the same reason, the log file of the configuration is also packed in the distribution. When the distribution is installed, these will find their way into the directory /log/kernel-version.