Custom Kernel Compilation with ABS
From ArchWiki
| i18n |
|---|
| English |
| 简体中文 |
| Italiano |
Introduction
There are many ways to build the kernel in arch, this is just one example - for other possibilities see Kernel Compilation. Some Arch users prefer the traditional way, however using ABS is helpful for automating certain tasks. The choice is yours; neither way is inherently better than the other.
This howto has been updated to provide a definitive PKGBUILD for the creation of custom kernel packages. It allows you to maintain multiple custom kernels with a unique naming scheme under pacman version control. It is ideal for ANY custom kernel build and can be easily adapted to fit many requirements. The PKGBUILD automatically accounts for the EXTRAVERSION and LOCALVERSION variables that are now fully supported in the kernel. EXTRAVERSION is frequently set by major patchsets such as -ck and -nitro. EXTRAVERSION is also used in the 2.6.x.y branch to carry the .y variable. LOCALVERSION can be set during the config stage and is the easiest and RECOMMENDED way to customize your kernel pkgnames. Simply setting LOCALVERSION to -custom or the date e.g. -20050105 will suffice! A unique LOCALVERSION guarantees a unique pkg.
Note that this is NOT an ABS howto - to successfully follow this HOWTO a working knowledge of building packages with ABS is ESSENTIAL - please read Arch Build System, The Arch package making HOW-TO - with guidelines and Patching in ABS.
Philosophy and Logic (how it works and why it works this way)
- The Arch Way - Keep It Simple.
- This PKGBUILD builds on the previous, widely accepted version.
- This build provides kernel packages and components with a simple, logical and uncomplicated naming scheme that ONLY uses variables that are part of the ABS system and part of the kernel compilation process itself. Rationale:
- The stock Arch kernel uses the
kernel26base pkgname which is logically extended here under the 2.6.x and 2.6.x.y schemes e.gkernel2611andkernel26117
These also provide the basis of/bootfilenames e.g.vmlinux26andvmlinuz26117 - The kernel compilation process uses the kernel version (2.6.x),
EXTRAVERSIONfrom theMakefileandCONFIG_LOCALVERSIONfrom the kernel config to create the name for the kernel's module directory, e.g.:
- The stock Arch kernel uses the
2.6.x$EXTRAVERSION$LOCALVERSION 2.6.11-cko2-ARCH/
- This is beyond the control of the PKGBUILD so to provide a pkg with similarly named components the PKGBUILD uses the same scheme to create unique
/bootfiles and a unique/usr/srcdirectory by appending-EXTRAVERSION-LOCALVERSION, e.g.:
/boot/vmlinuz2611-cko2-ARCH /boot/System.map2611-cko2-ARCH /boot/kconfig2611-cko2-ARCH /usr/src/linux-2.6.11-cko2-ARCH/
- If you have the recommended knowledge of ABS you will see that the PKGBUILD is transparently constructed, self-explanatory and can be customized easily.
- User input is almost identical to all ABS builds: simply set
pkgver,pkgrelandpkgdescand add additional sources, including patches, to thesourcearray. Patch users should insert the appropriate patch commands where indicated. Aside from uncommenting the config method and choosing whether tomake cleanor not the rest of the build is automated. - Having created a custom pkg naming scheme during the build, the PKGBUILD automatically corrects/updates itself with the new
pkgnamevariable allowing simplegensyncoperation.
Usage Notes
-
pkgnamemust be declared within 10 lines of the top of the PKGBUILD - so DO NOT move it - just leave it.
If you miss this simple instruction don't worry, it won't screw up your build but your PKGBUILD file will not have the pkgname automatically updated at the end of the build. This is to allow you to use gensync correctly BUT you can edit the PKGBUILD file manually afterwards of course.
- Until you have your own config that you are happy with it is easiest just to start with the default Arch config; you should also get the Arch
kernel26.installfile, make your ownkernel26.installscript or comment out the lineinstall=kernel26.installfrom the PKGBUILD. The official Arch files are both in your ABS tree, normally under/var/abs/core/kernel26. To download the ABS tree to your system simply runabsas root. It doesn't take long, even on dialup. You should keep this updated by runningabsas root on a regular basis.
- NOTE: If you use LILO or any other static bootloader (that is, one that requires update after every kernel change) you are advised to use an install file too. This is an example,
kernel26.install, for use with Lilo:
# arg 1: the new package version
# arg 2: the old package version
# Script by Jouke Witteveen (j <dot> witteveen <at> gmail)
# Revision: 4
link () {
dialog --backtitle "$ba" --title Linking --yesno
"\nDo you want to link /vmlinuz to the $ke kernel?\n(This can be useful for configuring your bootloader)" 9 60 &&{
[ -e /vmlinuz -o -h /vmlinuz ] &&\
mv -f /vmlinuz /vmlinuz.old
kern () {
ls -t /boot/vmlinuz$1* 2> /dev/null | head -n 1
}
vm=`kern \`echo $1 | sed "s|\.||g"\``
[ ! -e "$vm" ] &&\
vm=`kern`
ln -s $vm /vmlinuz
}
}
exec () {
dialog --backtitle "$ba" --title "Bootloader execution" --yesno
"\nDo you want to run Lilo to make the $ke kernel bootable?\n\n\
Remember: If you choose 'No' now you will not be able to boot the $ke kernel until you manually update your bootloader!" 12 60 &&\
lilo &&\
echo -e $1 # At least Lilo did not return an error
}
warn () {
dialog --backtitle "$ba" --title Warning --msgbox
"\nYou will not be able to boot the $ke kernel until you manually update your bootloader." 9 60
}
post_install () {
ba="Installing kernel $1"
ke="new"
link $1 &&\
exec "\nKernel $1 successfully installed!\n" ||\
warn
}
post_upgrade () {
ba="Upgrading kernel $2 to kernel $1"
ke="upgraded"
link $1
exec "\nKernel $2 successfully upgraded to version $1!\n" ||\
warn
}
post_remove () {
unli () {
[ -h $1 -a ! -e $1 ] &&\
unlink $1
}
unli /vmlinuz
unli /vmlinuz.old
[ -e /vmlinuz.old -a ! -e /vmlinuz ] &&{
ba="Removing kernel $1"
ke="old"
mv /vmlinuz.old /vmlinuz
exec "\nThe old kernel was successfully restored\n" ||\
warn
}
}
op=$1
shift
$op $*
- To check if
EXTRAVERSIONis set by your patchset try doing
grep +EXTRAVERSION= ./patchname
- and it should return something like this:
+EXTRAVERSION = -ck3
- if it doesn't then
EXTRAVERSIONis probably not being set by your patchset and you should ensure you use LOCALVERSION to customize the pkgname.
Arch default kernels are set with the-ARCHLOCALVERSIONvariable - you can set anything you like e.g.-custom(note the need for the preceding dash-)
Because of these added variables there is no need to alter the pkgname manually at any point or use any other variables. The build process automatically updates the pkgname variable in the PKGBUILD file at the end of each build to reflect the final full kernel version naming scheme.
- If used correctly this PKGBUILD should always provide a unique kernel build based on EXTRAVERSION and LOCALVERSION, and on the pkgver and pkgrel (as normal) - however it is up to the user to double check resulting pkgnames and contents before installation to prevent overwrites (see below for more details and examples).
Configuring the PKGBUILD
Note that this PKGBUILD cannot be used with kernel 2.4, which is no longer supported by Arch Linux. (news)
Copy the PKGBUILD below to your $startdir. Before building remember the following:
-
pkgnamecan be left as it is; it will automatically be set and correct itself. - Insert the
pkgverfor your kernel (for example:2.6.9). - Change the
pkgrelfor your current revision. You should increment this each time you make changes to the kernel config and want to build a REPLACEMENT pkg. If you don't want to replace the previous build but rather install in parallel you should useLOCALVERSIONto create a unique pkg. - Change/expand the
pkgdescto describe any patches or special config options applied. - Change the source to use a closer mirror and if you are using a patchset, add the patches to the source array.
- {OPTIONAL} Place the patch commands where indicated.
- Choose a make method by leaving your preferred method uncommented - gconfig (gtk based) xconfig (qt based) menuconfig (ncurses based).
- During the build you will be asked if you want to
make clean- the default isyes, replyNOif you know what you are doing.
# Contributor: dibblethewrecker <dibblethewrecker.at.jiwe.org>
pkgname=kernel26
pkgver=2.6.x.y
pkgrel=1
pkgdesc="The Linux Kernel 2.6.x.y and modules (IDE support)"
url="http://www.kernel.org"
depends=('module-init-tools')
install=kernel26.install
arch=(i686 x86_64)
license=('GPL')
##### add any patch sources to this section
source=(config ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$pkgver.tar.bz2 )
# Function to grab var from src
getvar() {
old=$(cat Makefile | grep "^$1")
echo $(echo ${old/"$1 ="/} | sed -e "s/[ ]*\(.*\)[ ]*/\1/g")
return 0
}
build() {
cd $srcdir/linux-$pkgver
##### Uncomment and apply any patches here
#patch -Np1 -i ../patchname || return 1
# get rid of the 'i' in i686
carch=`echo $CARCH | sed 's|i||'`
cat ../config | sed "s|#CARCH#|$carch|g" >./.config
##### Load config - uncomment your preferred config method
#yes "" | make config
#make oldconfig || return 1
#make menuconfig
#make xconfig
make gconfig
##### NO USER CHANGES BELOW HERE #####
# save the current pkgname
old_pkgname=$pkgname
# set pkgname for build purposes - DO NOT alter!
pkgname=kernel26
# save the updated config to build with today's date
cp ./.config $startdir/config-$(date +%b%d\-%Hh)
# get EXTRAVERSION from Makefile to create a unique pkgname and /usr/src directory
_kernextra=$(getvar "EXTRAVERSION")
# grab the 2.6.x.y version suffix from pkgver
_y="`echo $pkgver | cut --delim "." --fields 4`"
# remove .y version suffix from _kernextra
_kernextra="`echo $_kernextra | sed "s|\.$_y||g"`"
# Read the full kernel version info from new config to use in pathnames and pkgname
. ./.config
# Kernel custom - to create a unique pkgname (see below)
_kerncust="${_kernextra}${CONFIG_LOCALVERSION}"
# Kernel release - will be the same as Makefile
_kernrel="${pkgver}${_kerncust}"
# Get the pkgver suffix for unique pkgname and /boot file suffices
_pkgversuf="`echo $pkgver | sed "s|2.6.||g" | sed "s|\.||g"`"
# Set /boot file suffices from kernel release and pkgver suffix
_kernboot="${_pkgversuf}${_kerncust}"
# Set a new pkgname from kernel release and pkgver suffix
pkgname="${pkgname}${_pkgversuf}${_kerncust}"
# build!
echo
echo -n "Do you want to make clean (default YES)? (YES/NO): "
read choice
echo
echo -n "Press any key to start make or CTRL+C to quit"
read anykey
if [ "${choice}" = "NO" ] ; then
make bzImage modules || return 1
else
make clean bzImage modules || return 1
fi
mkdir -p $pkgdir/{lib/modules,boot}
make INSTALL_MOD_PATH=$pkgdir modules_install || return 1
cp System.map $pkgdir/boot/System.map26${_kernboot}
cp arch/i386/boot/bzImage $pkgdir/boot/vmlinuz26${_kernboot}
install -D -m644 Makefile \
$pkgdir/usr/src/linux-${_kernrel}/Makefile
install -D -m644 kernel/Makefile \
$pkgdir/usr/src/linux-${_kernrel}/kernel/Makefile
install -D -m644 .config \
$pkgdir/usr/src/linux-${_kernrel}/.config
install -D -m644 .kernelrelease \
$pkgdir/usr/src/linux-${_kernrel}/.kernelrelease
install -D -m644 .config $pkgdir/boot/kconfig26${_kernboot}
mkdir -p $pkgdir/usr/src/linux-${_kernrel}/include
mkdir -p $pkgdir/usr/src/linux-${_kernrel}/arch/i386/kernel
for i in acpi asm-generic asm-i386 config linux math-emu media net pcmcia scsi sound video; do
cp -a include/$i $pkgdir/usr/src/linux-${_kernrel}/include/
done
# copy files necessary for later builds, like nvidia and vmware
cp Module.symvers $pkgdir/usr/src/linux-${_kernrel}
cp -a scripts $pkgdir/usr/src/linux-${_kernrel}
mkdir -p $pkgdir/usr/src/linux-${_kernrel}/.tmp_versions
cp arch/i386/Makefile $pkgdir/usr/src/linux-${_kernrel}/arch/i386/
cp arch/i386/Makefile.cpu $pkgdir/usr/src/linux-${_kernrel}/arch/i386/
cp arch/i386/kernel/asm-offsets.s \
$pkgdir/usr/src/linux-${_kernrel}/arch/i386/kernel/
# copy in Kconfig files
for i in `find . -name "Kconfig*"`; do
mkdir -p $pkgdir/usr/src/linux-${_kernrel}/`echo $i | sed 's|/Kconfig.*||'`
cp $i $pkgdir/usr/src/linux-${_kernrel}/$i
done
cd $pkgdir/usr/src/linux-${_kernrel}/include && ln -s asm-i386 asm
chown -R root.root $pkgdir/usr/src/linux-${_kernrel}
cd $pkgdir/lib/modules/${_kernrel} && \
(rm -f source build; ln -sf /usr/src/linux-${_kernrel} build)
# Correct the pkgname in our PKGBUILD - this allows correct gensync operation
# NOTE: pkgname variable must be declared with first 10 lines of PKGBUILD!
cd $startdir
sed -i "1,11 s|pkgname=$old_pkgname|pkgname=$pkgname|" ./PKGBUILD
}
# vim:syntax=sh
- Install your new pkg as normal.
Your config file
PLEASE NOTE: during the build the final kernel config is stored in your $startdir as, for example, config-Apr13-12h. Your original config remains in the $startdir named config. If you wish to use the new config in another build make sure you copy the correct file!
Update Bootloader
- Remember to edit the bootloader (e.g. LILO or GRUB) configuration files to include an entry to the new kernel. The new kernel will install alongside any existing stock or custom kernels, so you may wish to keep a reference to your old kernel in the bootloader configuration file - at least, until you're sure the new one is working.
- If you use a static bootloader (one that requires update after every kernel change), remember to update it. For LILO, running
liloas root should suffice.
Other versions
There are several variations on this PKGBUILD available, they all provide identical results but the mechanics are slightly different:
- patch - includes the old
patch=variable. - verbose - provides Package Info (like that shown above) for review before starting the make process.
- buildstats - similar to verbose but writes more info, including build times, to a file called buildstats, which is stored in the $startdir. This can also be reviewed before starting the make process but also provides a permanent record.
I want the Arch logo!
Download the logo_linux_clut224.ppm to your $startdir from:
http://projects.archlinux.org/?p=linux-2.6-ARCH.git;a=tree;f=patches
Add the the file logo_linux_clut224.ppm to the source array, and add the copy command marked with (>>) below into the PKGBUILD as indicated:
##### Uncomment and apply any patches here #patch -Np1 -i ../patchname || return 1 >> ##### Arch logo - not compatible with gensplash! >> cp ../logo_linux_clut224.ppm drivers/video/logo/ # get rid of the 'i' in i686 carch=`echo $CARCH | sed 's|i||'` cat ../config | sed "s|#CARCH#|$carch|g" >./.config
The stock Arch config uses the following logo settings, ensure you set them at the config stage or use the stock config:
# # Logo configuration # CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y
Customization and Advanced Use (normal people can stop here)
Several people have successfully customized this PKGBUILD to their own needs, while others have derived a completely new approach from it. One customization recommended to people who make multiple builds of the same version for use in parallel is to add a sed command that automatically sets the CONFIG_LOCALVERSION variable in the config to a unique value before the config stage. This can be based on the date, your hostname, etc.
For example:
# get rid of the 'i' in i686
carch=`echo $CARCH | sed 's|i||'`
cat ../config | sed "s|#CARCH#|$carch|g" >./.config
>> # set LOCALVERSION to -date
>> sed -i "s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%y%m%d`|g" ./.config
##### Load config - uncomment your preferred config method
#yes "" | make config
or
# set LOCALVERSION to -date-hostname
sed -i "s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%y%m%d`-`hostname`|g" ./.config
For a truly unique LOCALVERSION you can set the date to seconds since 00:00:00 1970-01-01 UTC!
sed -i "s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%s`|g" ./.config
Problems
If you have problems with wrong package names try using the verbose PKGBUILD described in Other Versions above to see what naming scheme is being created before you commit to the build - you can quit with ctrl+c at most points before the make starts.
Using the nVIDIA video driver with your custom kernel
To use the nvidia driver with your new custom kernel, see: How to install NVIDIA driver with custom kernel
Feedback
If you have any questions/comments/suggestions about the above PKGBUILD feel free to join the discussion at: http://bbs.archlinux.org/viewtopic.php?t=9272
Some suggestions have already been incorporated but please consider the Keep It Simple philosophy and remember the original goal. Kernel compilation is a very individual process and there are a HUGE variety of ways to go about it. This PKGBUILD does not even attempt to account for all eventualities, it would be fruitless to try but of course you are completely free to customize this build to your precise needs. Best of luck!
DibbleTheWrecker