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
kernel26
base pkgname which is logically extended here under the 2.6.x and 2.6.x.y schemes e.gkernel2611
andkernel26117
These also provide the basis of/boot
filenames e.g.vmlinux26
andvmlinuz26117
- The kernel compilation process uses the kernel version (2.6.x),
EXTRAVERSION
from theMakefile
andCONFIG_LOCALVERSION
from 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
/boot
files and a unique/usr/src
directory 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
,pkgrel
andpkgdesc
and add additional sources, including patches, to thesource
array. Patch users should insert the appropriate patch commands where indicated. Aside from uncommenting the config method and choosing whether tomake 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 simplegensync
operation.
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 ownkernel26.install
script or comment out the lineinstall=kernel26.install
from 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 runabs
as root. It doesn't take long, even on dialup. You should keep this updated by runningabs
as 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
EXTRAVERSION
is set by your patchset try doing
grep +EXTRAVERSION= ./patchname
- and it should return something like this:
+EXTRAVERSION = -ck3
- 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
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:
-
pkgname
can be left as it is; it will automatically be set and correct itself. - Insert the
pkgver
for your kernel (for example:2.6.9
). - 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 useLOCALVERSION
to create a unique pkg. - Change/expand the
pkgdesc
to 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
, replyNO
if 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
lilo
as 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