Difference between revisions of "Custom Kernel Compilation with ABS"

From ArchWiki
Jump to: navigation, search
m (I want the Arch logo!: - updated logo location, language cleanup.)
m (Using the nVIDIA video driver with your custom kernel: proper wikilink)
Line 361: Line 361:
=== Using the nVIDIA video driver with your custom kernel ===
=== Using the nVIDIA video driver with your custom kernel ===
To use the nvidia driver with your new custom kernel, see: [http://wiki.archlinux.org/index.php/NVIDIA#How_to_install_NVIDIA_Driver_with_custom_kernel How to install nVIDIA driver with custom kernel]
To use the nvidia driver with your new custom kernel, see: [[NVIDIA#How_to_install_NVIDIA_Driver_with_custom_kernel|How to install NVIDIA driver with custom kernel]]
=== Feedback ===
=== Feedback ===

Revision as of 21:15, 27 June 2008

Template:I18n links start Template:I18n entry Template:I18n entry Template:I18n entry Template:I18n links end


You can choose to compile your custom kernel the traditional way, or via ABS (this guide). 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.

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 kernel26 base pkgname which is logically extended here under the 2.6.x and 2.6.x.y schemes e.g kernel2611 and kernel26117
      These also provide the basis of /boot filenames e.g. vmlinux26 and vmlinuz26117
    • The kernel compilation process uses the kernel version (2.6.x), EXTRAVERSION from the Makefile and CONFIG_LOCALVERSION from the kernel config to create the name for the kernel's module directory, e.g.:
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 /boot files and a unique /usr/src directory by appending -EXTRAVERSION-LOCALVERSION, e.g.:

  • If you have the recommended knowledge of ABS you will see that the PKGBUILD is transparently constructed, self-explanatory and easily customized.
  • User input is almost identical to all ABS builds: simply set pkgver, pkgrel and pkgdesc and add additional sources, including patches, to the source array. Patch users should insert the appropriate patch commands where indicated. Aside from uncommenting the config method and choosing whether to make clean or 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 pkgname variable allowing simple gensync operation.


  1. This PKGBUILD is only suited to builds of the 2.6 kernel branch - kernel 2.4 is no longer supported in Arch Linux (news)
  2. This is NOT an ABS howto - to successfully follow this HOWTO a working knowledge of building pkgs with ABS is ESSENTIAL - please read ABS - The Arch Build System, The Arch package making HOW-TO - with guidelines and Patching in ABS

I don't advise you build a kernel for your first ABS project. If you need guidelines on how to use fakeroot or set up a build directory read the other documents first.

  1. Likewise it helps if you know how to configure a kernel! If this is your first effort building a kernel I strongly recommend you start from the default Arch config, this is detailed further below.

Usage Notes

  • pkgname must 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.install file, make your own kernel26.install script or comment out the line install=kernel26.install from the PKGBUILD. The official Arch files are both in your ABS tree, normally under /var/abs/kernels/kernel26. To download the ABS tree to your system simply run abs as root. It doesn't take long, even on dialup. You should keep this updated by running abs as root on a regular basis.
NOTE: If you use Lilo or any other static bootloader you are adviced to use an install file to, at least, remember yourself to update your bootloader after the installation of your bootloader. 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" ] &&\
    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"
  link $1 &&\
    exec "\nKernel $1 successfully installed!\n" ||\

post_upgrade () {
  ba="Upgrading kernel $2 to kernel $1"
  link $1
  exec "\nKernel $2 successfully upgraded to version $1!\n" ||\

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"
    mv /vmlinuz.old /vmlinuz
    exec "\nThe old kernel was successfully restored\n" ||\


$op $*

  • To check if EXTRAVERSION is set by your patchset try doing
grep +EXTRAVERSION= ./patchname
and it should return something like this:
if it doesn't then EXTRAVERSION is 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 -ARCH LOCALVERSION variable - 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

Copy the PKGBUILD below to your $startdir. The PKGBUILD can also be downloaded from here. Before building remember the following:

  1. pkgname can be left as it is; it will automatically be set and correct itself.
  2. Insert the pkgver for your kernel (for example: 2.6.9).
  3. Change the pkgrel for 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 use LOCALVERSION to create a unique pkg.
  4. Change/expand the pkgdesc to describe any patches or special config options applied.
  5. Change the source to use a closer mirror and if you are using a patchset, add the patches to the source array.
  6. {OPTIONAL} Place the patch commands where indicated.
  7. Choose a make method by leaving your preferred method uncommented - gconfig (gtk based) xconfig (qt based) menuconfig (ncurses based).
  8. During the build you will be asked if you want to make clean - the default is yes, reply NO if you know what you are doing.
# Contributor: dibblethewrecker <dibblethewrecker.at.jiwe.org>
pkgdesc="The Linux Kernel 2.6.x.y and modules (IDE support)"
arch=(i686 x86_64)

##### 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 $startdir/src/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


  # save the current pkgname

  # set pkgname for build purposes - DO NOT alter!

  # 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)
  # Kernel release - will be the same as Makefile
  # 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

  # Set a new pkgname from  kernel release and pkgver suffix

  # build!
  echo -n "Do you want to make clean (default YES)? (YES/NO): "
  read choice
  echo -n "Press any key to start make or CTRL+C to quit"
  read anykey

  if [ "${choice}" = "NO" ] ; then
  	make bzImage modules || return 1
	make clean bzImage modules || return 1

  mkdir -p $startdir/pkg/{lib/modules,boot}
  make INSTALL_MOD_PATH=$startdir/pkg modules_install || return 1
  cp System.map $startdir/pkg/boot/System.map26${_kernboot}
  cp arch/i386/boot/bzImage $startdir/pkg/boot/vmlinuz26${_kernboot}
  install -D -m644 Makefile \
  install -D -m644 kernel/Makefile \
  install -D -m644 .config \
  install -D -m644 .kernelrelease \
  install -D -m644 .config $startdir/pkg/boot/kconfig26${_kernboot}
  mkdir -p $startdir/pkg/usr/src/linux-${_kernrel}/include
  mkdir -p $startdir/pkg/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 $startdir/pkg/usr/src/linux-${_kernrel}/include/
  # copy files necessary for later builds, like nvidia and vmware
  cp Module.symvers $startdir/pkg/usr/src/linux-${_kernrel}
  cp -a scripts $startdir/pkg/usr/src/linux-${_kernrel}
  mkdir -p $startdir/pkg/usr/src/linux-${_kernrel}/.tmp_versions
  cp arch/i386/Makefile $startdir/pkg/usr/src/linux-${_kernrel}/arch/i386/
  cp arch/i386/Makefile.cpu $startdir/pkg/usr/src/linux-${_kernrel}/arch/i386/
  cp arch/i386/kernel/asm-offsets.s \
  # copy in Kconfig files
  for i in `find . -name "Kconfig*"`; do
    mkdir -p $startdir/pkg/usr/src/linux-${_kernrel}/`echo $i | sed 's|/Kconfig.*||'`
    cp $i $startdir/pkg/usr/src/linux-${_kernrel}/$i
  cd $startdir/pkg/usr/src/linux-${_kernrel}/include && ln -s asm-i386 asm
  chown -R root.root $startdir/pkg/usr/src/linux-${_kernrel}
  cd $startdir/pkg/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 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 config file, at least until you know the new one is working. THIS IS STRONGLY RECOMMENDED!
  • If you use lilo remember to run lilo to update it.

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:


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

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


    # 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


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


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!