Kernel Compilation with ABS

From ArchWiki

Jump to: navigation, search


There are many ways to build the kernel in arch, this is just one example for other possibilities see Kernel Compilation

The following PKGBUILD is a revision of the great work contributed by IceRAM (found previously on the forums) which is the basis of the current Kernel Compilation with ABS page. There is also an alternative wiki guide contributed by Arch developer DibbletheWrecker, entitled Custom Kernel Compilation with ABS which may interest you as well.

Contents

How To Use

This PKGBUILD is designed to give users the ability to build and install in parallel both kernels with separate patchsets and configurations applied. Though that was the design, it can be used for simple kernel compilation and you may communicate as little information in your package names as you wish by leaving the optional patchset and cfgname fields blank.

It is important to understand what changes will be considered (a) only a package version change, resulting in an on-top-of installation, versus (b) a package name change, which causes an in-parallel installation.

Any change to the ~patchset or ~cfgname will result in a new package name. If these do not change, then changes to the ~kerver, ~extraver, and pkgrel will only cause a change to the package version. This means, by design, updated kernels sources with the same patch trees, or updated releases of a batchtree (ck6->ck7) will be treated as a version change and install on top of the previous version. Please see the "Possible Questions" section below for a discussion of this behavior if this is not what you wanted.

Kernel Prototype PKGBUILD

#############################################
# Linux Kernel and Modules PKGBUILD prototype
#
# This PKGBUILD provides a structure to build, install, and remove
# versions of kernels from different trees and with different options
# enabled in the config file.

_desc="Linux Kernel and Modules"
_pkg_base="kernel"
_patchset=""
_cfgname=""
_kerver=2.6.X.Y
_extraver=""  # Use _ instead of - in _extraver! Ex: mm4_ck7
pkgrel=1
arch=('i686') # change this to your arch (e.g.: x86_64)
url="http://www.kernel.org"
license=('GPL')
depends=('module-init-tools')
makedepends=('bzip2' 'gcc')

# PAGE DOWN TWO PAGES FOR PATCHES AND MD5 SUMS
#
#
# The preceding information is used to configure the build:
#
# _desc:
#    This is the base of the package description.  It should be
#    okay to leave the default value of "Linux Kernel and Modules"
#
# _pkg_base:
#    This is the base of the pkgname.  It should be okay to leave
#    this with the default value of "kernel"
#
# _patchset: [optional - set to "" to not use]
#    This value is an identifier which you can use to indicate
#    what patches are being applied to the kernel.  Examples would be:
#    ck - Indicates following Con Kolivas' patch sets
#    mm - Indicates kernel is patched with Andrew Morton's tree
#    acpi - Indicates patches have been added for acpi
#    ck_acpi_no_r4 - Indicates the source is patched with Kon Colivas'
#       patchset, acpi patches are applied, and reiser4 patches have
#       been removed.
#    Recommendation: Add an identifier for any tree you follow, but don't
#       get too carried away.  You may include hyphens, but I strongly
#       recommend underscores instead.
#
# _cfgname: [optional - set to "" to not use]
#    This value is an identifier used to indicate how the kernel is
#    configured.  Whereas patchset should indicate manipulations to then
#    source tree, here you should indicate changes to the default config.
#    Examples:
#    sn45g - The kernel is configured with drivers and modules found in
#       Shuttle's SN45G XPC.
#    test - This kernel is a test of a different or new configuration
#    Recommendation: You may use hyphens but I strongly suggest underscores
#       instead.  Leave blank ("") to indicate the kernel is configured
#       with the same options as the current Arch stock kernel package.
#
# _kerver:
#    This is the version of the kernel source tree that is going to be
#    downloaded.  (ex: 2.6.5 or 2.6.8.1)
#
# _extraver:
#    This is additional version information for the kernel.  This should
#    reflect any kernel version modifiers that will be applied by the
#    patches you are going to apply.  Example:
#    ck7 - This kernel version will have "-ck7" appended to indicate it is
#       patched with the 7th release of Con Kolivas' patches against the
#       current (_kerver) kernel version.
#    Recommendation: Including a ck7 here may seem redundant to including
#       a ck in the _patchset value.  I strongly recommend doing it in
#       both places.  A ck in the _patchset indicates the nature of then
#       source tree, but is not used in the arch pkgver.  The ck7 inside
#       _extraver will be applied as part of the pkgver.
#
#  pkgrel:
#     This is the standard Arch pkgrel value.  Start at one for each
#     release of a new combination of _patchset, _cfgname, _kerver, and
#     _extraver.  Increment by one for each repackaging where those four
#     values remain the same.
#
#  The generated package will have the following properties:
#    name: $_pkg_base-$_patchset-$_cfgname
#    version: $_kerver_$_extraver-#pkgrel
#    pkg: kernel-$_patchset-$_cfgname-$_kerver_$_extraver-$pkgrel.pkg.tar.gz
#    vmlinuz-$_kerver-$_extraver-$_patchset-$_cfgname
#    System.map-$_kerver-$_extraver-$_patchset-$_cfgname
#    kconfig-$_kerver-$_extraver-$_patchset-$_cfgname
#    /lib/modules/$_kerver-$_extraver-$_patchset-$_cfgname
#    /usr/src/linux-$_kerver-$_extraver-$_patchset-$_cfgname
#    /usr/src/linux -> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#    /usr/src/linux/config.stock = a stock arch kernel config file
#    A copy of the .config use to build the kernel will be copied to
#       the abs build directory.
#

#############################################
#DO NOT CHANGE INSIDE THIS BLOCK
pkgver=$_kerver

if [ ! -z "$_extraver" ]; then
  _scratch="_$_extraver"
  pkgver=$pkgver$_scratch
  _extraver=-${_extraver/_/-}
fi

pkgdesc="$_desc - ver: $_kerver$_extraver;"
pkgname=$_pkg_base

if [ ! -z "$_patchset" ]; then
  pkgdesc="$pkgdesc pset: $_patchset;"
  _patchset="-$_patchset"
  pkgname="$pkgname$_patchset"
fi

if [ ! -z "$_cfgname" ]; then
  pkgdesc="$pkgdesc cfg: $_cfgname;"
  _cfgname="-$_cfgname"
  pkgname="$pkgname$_cfgname"
fi

pkgdesc="$pkgdesc bld: $pkgrel"
_idstr="$_kerver$_extraver$_patchset$_cfgname"
#############################################

###### Add patchfiles to the source array.  Make sure the config file matches
###### the configuration for the kernel you intend to package.  Make sure the
###### config.stock matches the .config from the current Arch stock kernel.
source=(ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kerver.tar.bz2
  config
  config.stock
  )

###### Add md5 checksums here:
md5sums=()

getvar() {
  old=$(cat Makefile | grep "^$1")
  echo $(echo ${old/"$1 ="/} | sed -e "s/[ ]*\(.*\)[ ]*/\1/g")
  return 0
}

build() {
  echo "_pkg_base: $_pkg_base"
  echo "_patchset: $_patchset"
  echo "_cfgname: $_cfgname"
  echo "_kerver: $_kerver"
  echo "_extraver: $_extraver"
  echo "pkgrel: $pkgrel"
  echo "_desc: $_desc"
  echo "url: $url"
  echo "license: $license"
  echo "pkgver: $pkgver"
  echo "pkgdesc: $pkgdesc"
  echo "_idstr: $_idstr"
  #read KEY

  cd ${srcdir}/linux-$_kerver

###### apply patches here
  # patch -p1 < ../patch1 || return 1

  #get rid of i in i686 in default config
  carch=${CARCH/i/}
  cat ../config | sed "s|#CARCH#|$carch|g" >./.config

###### Choose one of the following configuration types
  #make oldconfig || return 1
  #make menuconfig || return 1
  #make xconfig || return 1 #### (BROKEN?)
  make gconfig || return 1

#############################################
# NO CHANGES BELOW THIS POINT

  # Save the configuration file to a backup in the build directory
  cp ./.config ../../config$_cfgname.bak

  # set EXTRAVERSION to help use unique /lib/modules/ subdirectories
  _ker_make_ver=$(getvar "VERSION").$(getvar "PATCHLEVEL").$(getvar "SUBLEVEL")
  _ker_extraver=`echo $_idstr | sed "s|^$_ker_make_ver||"`

  # update EXTRAVERSION in the Makefile by adding our (for modules location)
  _oldline=$(cat Makefile | grep "^EXTRAVERSION")
  cat Makefile | sed "s|$_oldline|EXTRAVERSION\ =\ $_ker_extraver$_patchset$_cfgname|" > tmpMake
  mv tmpMake Makefile

  make clean bzImage modules || return 1
  mkdir -p ${pkgdir}/{lib/modules,boot}
  make INSTALL_MOD_PATH=${pkgdir} modules_install || return 1

  # create unique names in /boot/
  cp System.map ${pkgdir}/boot/System.map-$_idstr
  cp arch/$arch/boot/bzImage ${pkgdir}/boot/vmlinuz-$_idstr

  install -D -m644 Makefile ${pkgdir}/usr/src/linux-$_idstr/Makefile
  install -D -m644 .config ${pkgdir}/usr/src/linux-$_idstr/.config
  install -D -m644 ../config.stock ${pkgdir}/usr/src/linux-$_idstr/config.stock
  install -D -m644 .config ${pkgdir}/boot/kconfig-$_idstr
  mkdir -p ${pkgdir}/usr/src/linux-$_idstr/include
  mkdir -p ${pkgdir}/usr/src/linux-$_idstr/arch/$arch/kernel
  for i in acpi asm-generic asm-x86 config linux math-emu net pcmcia scsi video; do
    cp -a include/$i ${pkgdir}/usr/src/linux-$_idstr/include/
  done

  # copy files necessary for later builds, like nvidia and vmware
  cp -a scripts ${pkgdir}/usr/src/linux-$_idstr/
  mkdir -p ${pkgdir}/usr/src/linux-$_idstr/.tmp_versions
  cp arch/$arch/Makefile ${pkgdir}/usr/src/linux-$_idstr/arch/$arch/
  cp arch/$arch/kernel/asm-offsets.s ${pkgdir}/usr/src/linux-$_idstr/arch/$arch/kernel/

  # copy in Kconfig files
  for i in `find . -name "Kconfig*"`; do
    mkdir -p ${pkgdir}/usr/src/linux-$_idstr/`echo $i | sed 's|/Kconfig.*||'`
    cp $i ${pkgdir}/usr/src/linux-$_idstr/$i
  done
  cd ${pkgdir}/usr/src/linux-$_idstr/include && ln -s asm-x86 asm
  chown -R root.root ${pkgdir}/usr/src/linux-$_idstr

  cd ${pkgdir}/lib/modules/$_idstr && \
    (rm -f build; ln -sf /usr/src/linux-$_idstr build)

  ln -sf /usr/src/linux-$_idstr ${pkgdir}/usr/src/linux

  cp ${srcdir}/config.stock ${pkgdir}/usr/src/linux-$_idstr/config.stock
}

Though covered in the comments of the PKGBUILD, a brief repeat of the tunables and results seems warranted:

Tunables

_desc:

This is the base of the package description. The default value of "Linux Kernel and Modules" should be acceptable. Additional descriptive text derived from the other variables will be appended to form the final package description.

pkgbase:

This is the base of the package name. The default value of "kernel" should be acceptable.

_patchset:

This optional field will be part of the package name. It should briefly indicate what patches are being applied to the source tree. It is strongly recommended that you include an indicator for patches from kernel branches (ck, mm, VP, etc) as well as any deviation from those trees (like noreiser4). You should not include the actual version of the ck or mm patches in this field. That information will be supplied in extraver. Likewise, you should not indicate kernel config changes here as that is indicated in _cfgname.

_cfgname:

This optional field will be part of the package name. It should briefly indicate what type of choices were made in the kernel config. Examples would be "sn45g" to indicate the config is customized for a particular kind of computer, or "test" to indicate you are testing a different configuration, or "nofb" if you disabled the framebuffer. It is strongly recommended that you leave this blank ("") to indicate a stock Arch kernel config. You could also use this field to indicate architecture restrictions of the kernel from makepkg.conf compile options - "athlon" perhaps for an athlon specific build.

_kerver:

This field indicates the version of the linux kernel sources that will be downloaded and used in the compilation. This field should NOT include modifiers such as \"-ck7\" as that information will be supplied in _extraver.

_extraver:

This field contains the extra version information to be appended to the kerver. Examples include \"ck7\". You should include the version of the ck or mm patches included as this will be used as part of the package version. While it is customary to see kernels reffered to as 2.6.8.1-ck7, do NOT use any hypens in this field. A pacman limitation requires you to use underscores instead.

pkgrel:

This is the standard PKGBUILD pkgrel variable. This should be set to 1 whenever a change is made to any of the patchset, cfgname, kerver, or extraver variables. Repackages of the kernel with NO change to those variables should see the pkgrel variable incremented +1.

Results

Package Name:
The name of this package will be a combination of the pkgbase, patchset, and _cfgname separated by hyphens.

Package Version:
The version of this package will be a combination of the kerver, extraver separated by underscores and the pkgbuil will be appended on the end separated by a hyphen.

Package File:
The package filename will be: kernel-$patchset-$cfgname-$kerver$_extraver-$pkgrel.pkg.tar.gz

/boot Files:

vmlinuz-$kerver-$extraver-$patchset-$cfgname 
System.map-$kerver-$extraver-$patchset-$cfgname
kconfig-$kerver-$extraver-$patchset-$cfgname

Modules:
Modules will be placed in /lib/modules/$kerver-$extraver-$patchset-$cfgname

Source:
The kernel source directory will be copied to /usr/src/linux-$kerver-$extraver-$patchset-$cfgname Note: /usr/src/linux will be mapped to this directory upon installation.


Using the nVIDIA video driver with your custom kernel

To use the nvidia driver with your new custom kernel, see: NVIDIA#Installing_the_driver_while_using_a_custom_kernel


Possible Questions


Why are the kerver and extraver separated by underscores in the package version and package file yet they are separated by hyphens (dashes) in the installed files and directories?

As much as I'd love to be consistent the current version of pacman makes the assumption that the package version will only contain one hyphen - the one separating the package release variable. So using hyphens in the actual package version is out, at least for now. Further, I decided it was better for the on-disk installed files to be inconsitant with the package version so they could maintain consistancy with the kernel developers notation.

This is too complex. What was lacking in the old kernel PKGBUILD prototpye?

Well, while it was very good, I wanted to more cleanly separate the concepts of kernel version, patches applied, and configurations. The old version had one custom variable, but I wanted to split that apart. Further, that version modified the package version variable in the build() procedure. That is considered a no-no and can lead to packages that will install but cannot be removed. This problem really arises when using patchsets (like the -ck or -mm trees) that modify the kernel source's EXTRAVERSION.

I want to install new kernel versions in parallel, not on top. Why doesn't your PKGBUILD facilitate that

Great question. First let me explain the rationale for the way things are and then I'll offer some suggestion for accomplishing what you want.

The idea behind this PKGBUILD is that a user can have multiple parallel kernels installed for different trees and/or different configurations. For instance, I might want to keep separate kernels packaged up for my dell desktop hardware, my laptop hardware, the able to run everything stock kernel, and then Con Kolivas' more experimental interactivity patches.

Jane Doe might like Con's interactive desktop patches but feels that the reiser4 changes have unresolved locking issues. She might maintain a package kernel-cknor4. John Smith, less of a power user, might like Jane's kernel and want to pull from her. He can stay up to date by installing her package and then update to new versions which she makes. Those version can include updates to the patchsets as well as the underlying kernel sources.

But I understand you might want to keep versions in parallel. In fact, Jane Doe wants to do that when she tests a new release from Con. To do this, she keeps a separate, in parallel, package called kernel-cknor4-dev where she uses the cfgname to add the \"dev\" identifier. Jane can install this in parallel with her regular kernel-cknor4 package. Once Jane is satisfied that the new patches (perhaps ck8 instead of ck7) are stable, she can repackage them in kernel-cknor4 (with no dev). This way John Smith can transparently update to the new tested version.

Dependency Suggestion

If you are making a new kernel package that only differs from the vanilla kernel package by one or two CONFIGs you might want to just tell people to change these CONFIGs and not create a whole new package. If packages are known to depend on CONFIG_X_Y=m or CONFIG_X_Y=y, that's a problem because kernel CONFIG options are not packages to be included in a depends array in a PKGBUILD. This problem can be solved if the following script becomes the norm for kernel PKGBUILDS:

cat .config | grep -E '(=y|=m)' | sed -e 's/CONFIG_/kernel26-/g' | sed -e 's/=[ym]$//g' | sed -e 's/_/-/g' | tr "[:upper:]" "[:lower:]" > file

_wcoutput=`wc -l file`
_linecount=${_wcoutput:0:${#_wcoutput}-5}

for ((i=1;i<=_linecount;i++)) do
  provides[i]=`head -$i file | tail -1`
done

rm file

This should be placed right under the line where you create the .config file. This way every option such as CONFIG_X_Y=m or CONFIG_X_Y=y will become a virtual package called kernel26-x-y provided by your kernel. The indices above start at 1 so they assume that your kernel provides kernel26 already. If your kernel provides two packages already you'll want to replace provides[i] with provides[i+1]. If everyone does this packages will no longer need to depend on specific kernels, just specific CONFIGs.

Personal tools