Kernel-packaging
Creating a Custom Package of Kernel and Modules
- Note: This tutorial assumes that you know how to compile a kernel already. It only looks at a way of creating a package and doesn't aim to show kernel config options.
For info on compiling please look at these pages:
- Note2: I will be assuming x86 here, but if anyone wants to contribute some notes on x86_64 until I can get a machine setup, please do.
Kernel Output Target Option
The usual way to make any sort of package is via the $DESTDIR variable. The kernel doesn't use this however, but it does have an O switch which does the same thing, although the output might not be exactly what you expect.
The first job is to create an output directory. I will be using /tmp/kernel-build for this so mkdir it now.
Output Into a Build Directory
From your kernel source directory do
make O=/tmp/kernel-build menuconfig
(or whichever method you prefer.)
make mrproper
This will delete your .config in the source tree so make sure you have a copy of it somewhere for safe keeping.
Next steps are the same as a normal make and modules_install, but again using the O= switch:
make O=/tmp/kernel-build make O=/tmp/kernel-build modules_install
- Note: Do not use 'make install' as this *will* install it in /boot rather than our build directory.
At this point everything we need is in the build directory. However, taking a look inside it shows many more things have been placed there than we need. The kernel is in arch/x86/boot/ as usual and the modules are in various directories. Luckily for us there is a file, modules.order, which lists the modules to be installed and that we can use to help us make a package.
Installing Modules and Kernel to our Package Directory
Ok let's use /tmp/kernel-package for our package directory. Also let's assume a 2.6.29.6 kernel with jabberwok as local name. A little bash will copy our modules to it:
for i in $(cat modules.order | sed "s#^kernel/##") do mkdir -p /tmp/kernel-package/lib/modules/2.6.29.6-jabberwok/$(dirname $i) install -m 644 -v $i /tmp/kernel-package/lib/modules/2.6.29.6-jabberwok/$(dirname $i) done
Now we need the kernel and associated files.
mkdir /tmp/kernel-package/boot cp arch/x86/boot/bzImage /tmp/kernel-package/boot/vmlinuz-2.6.29.6-jabberwok cp System.map /tmp/kernel-package/boot/System.map-2.6.29.6-jabberwok cp .config /tmp/kernel-package/boot/config-2.6.29.6-jabberwok
And then the doinst.sh and slack-desc.
mkdir /tmp/kernel-package/install echo "/sbin/depmod -a" > /tmp/kernel-package/install/doinst.sh
I'll leave you to figure out the slack-desc. It should be copied into the install/ directory and appname ought to be (going by this example) kernel-jabberwok.
Making the Package
cd /tmp/kernel-package /sbin/makepkg -l y -c n /tmp/kernel-jabberwok-2.6.29.6_tag-i686-1.txz
Change '_tag' to your usual moniker. Hopefully we now have a package in /tmp. Copy it to a temporary directory somewhere, explodepkg it and check the contents. We don't want to install something with messed up paths etc. If all is well we can installpkg it.
As usual, edit your /etc/lilo.conf and add an option for the new kernel, keeping the old kernel entry in place for safety, then run lilo.
A Little Automation
Of course this would be easier to control with a script rather than typing in these commands manually and trying not to make typos. Here is the script that I've been using:
#!/bin/bash KARCH=${ARCH:-i486} ARCH=x86 MODULELIST=modules.order PRGNAM=kernel VERSION=${VERSION:-2.6.29.6} BUILD=${BUILD:-1} TAG=${TAG:-_daw} LOCALNAME=${LOCALNAME:-jabberwok} OUTPUT=${TMP:-/tmp} KOUTPUT=$OUTPUT/$PRGNAM-$LOCALNAME PKG=$OUTPUT/$PRGNAM-$LOCALNAME-$VERSION MODDIR=$PKG/lib/modules/$VERSION-$LOCALNAME set -e rm -rf $KOUTPUT rm -rf $PKG mkdir -p $KOUTPUT cd $SOURCE make O=$KOUTPUT menuconfig make mrproper make O=$KOUTPUT make O=$KOUTPUT modules_install cd $KOUTPUT for i in $(cat $MODULELIST | sed "s#^kernel/##") do mkdir -p $MODDDIR/$(dirname $i) install -m 644 -v $i $MODDDIR/$(dirname $i) done mkdir -p $PKG/boot cp arch/x86/boot/bzImage $PKG/boot/vmlinuz-$VERSION-$LOCALNAME cp System.map $PKG/boot/System.map-$VERSION-$LOCALNAME cp .config $PKG/boot/config-$VERSION-$LOCALNAME mkdir $PKG/install echo "/sbin/depmod -a" > $PKG/install/doinst.sh cat << EOF > $PKG/install/slack-desc # HOW TO EDIT THIS FILE: # The "handy ruler" below makes it easier to edit a package description. Line # up the first '|' above the ':' following the base package name, and the '|' # on the right side marks the last column you can put a character in. You must # make exactly 11 lines for the formatting to be correct. It's also # customary to leave one space after the ':'. $PRGNAM-$LOCALNAME|-----handy-ruler------------------------------------------------------| $PRGNAM-$LOCALNAME: kernel and modules 2.6.29.6-jabberwok $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: Jabberwokky type kernel! $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: $PRGNAM-$LOCALNAME: EOF cd $PKG /sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$LOCALNAME-$VERSION$TAG-$KARCH-$BUILD.${PKGTYPE:-tgz}
And here's a downloadable version: http://www.dawoodfall.net/slackbuilds/13.0/kernel/kernel-jabberwok.SlackBuild
Conclusion
The aim for doing this was to be able to build a kernel for my old T42 on my desktop box using the T42's .config. It could be possible to split up kernel and modules into separate packages but I'll let you figure out the details. Note that this does not include the firmware so you should keep the relevant kernel-firmware package installed.
At the end of the day, this helped me to compile a kernel without my laptop getting even warm, which was the point of the project.
--Dive 04:31, 11 March 2010 (UTC)