Custom Kernel Compilation with ABS (简体中文)

From ArchWiki
Revision as of 00:05, 13 March 2010 by Mr.Elendig (Talk | contribs) (marked out of date, almost all the info is wrong/not relevant anymore)

Jump to: navigation, search


Tango-view-refresh-red.pngThis article or section is out of date.Tango-view-refresh-red.png

Reason: please use the first argument of the template to provide a brief explanation. (Discuss in Talk:Custom Kernel Compilation with ABS (简体中文)#)

This template has only maintenance purposes. For linking to local translations please use interlanguage links, see Help:i18n#Interlanguage links.


Local languages: Català – Dansk – English – Español – Esperanto – Hrvatski – Indonesia – Italiano – Lietuviškai – Magyar – Nederlands – Norsk Bokmål – Polski – Português – Slovenský – Česky – Ελληνικά – Български – Русский – Српски – Українська – עברית – العربية – ไทย – 日本語 – 正體中文 – 简体中文 – 한국어


External languages (all articles in these languages should be moved to the external wiki): Deutsch – Français – Română – Suomi – Svenska – Tiếng Việt – Türkçe – فارسی

这一篇翻译得比较吃力,哪位大侠帮着校正一下吧:英文原文

介绍

你可以通过传统方法或者ABS来编译自定义内核。一小部分Arch用户更喜欢前一种方法,但是ABS更加自动化。两种方法没有本质上的优劣,使用哪种方法完全是你自己的选择。

我们将会给出一个有效地可以用来创建自定义内核的PKGBUILD文件,理想情况下你只需要按照自己的条件填写一些变量就可以创建自己的内核。PKGBUILD文件自动解决EXTRAVERSIONLOCALVERSION。前者一般表示主补丁代号(如-ck,-nitro);后者用来自定义内核名称。建议简单地把LOCALVERSION设为-custom或创建日期(如-20050105)。唯一的LOCALVERSION可以保证生成唯一的内核包。

哲学与逻辑(知其然,并知其所以然)

  • Arch之道 - KISS
  • 该PKGBUILD基于以前被广泛接受的版本
  • 该文件使用简单、合理的命名方案,只使用ABS系统及内核编译过程所需的变量:
    • Arch官方内核包一般命名为kernel26,我们根据内核版本2.6.x或2.6.x.y将包名称记为kernel2611kernel26117
      生成的内核镜像文件名类似于vmlinux26vmlinuz26117
    • 在内核编译过程中,从Makefile中提取EXTRAVERSION,从内核配置文件(.config)中提取CONFIG_LOCALVERSION,与内核版本(2.6.x)组合在一起形成新的内核版本:
2.6.x$EXTRAVERSION$LOCALVERSION
2.6.11-cko2-ARCH/

利用上面的版本号创建唯一的镜像名称、源目录名称:

/boot/vmlinuz2611-cko2-ARCH
/boot/System.map2611-cko2-ARCH
/boot/kconfig2611-cko2-ARCH
/usr/src/linux-2.6.11-cko2-ARCH/
  • 如果你了解ABS系统,可以自己察看PKGBUILD文件,并根据自己的需要进行修改;
  • 用户输入基本是相同的,简单地设置以下几个变量:pkgver, pkgrelpkgdesc,并添加额外的源,把补丁加入source数组。在指定的位置加入补丁命令,选择是否make clean。剩下的步骤都是自动完成的。
  • 创建了自定义命名方案后,PKGBUILD会自动根据新的pkgname修正/升级,并允许简单的gensync操作。

注意

  1. 该PKGBUILD文件只适合于创建2.6内核包;
  2. 你需要具备利用ABS系统创建软件包的知识。可以参考ABS - The Arch Build System, Creating Packages and Patching in ABS

我建议你不要拿内核作为你ABS的第一个实验品。如果你想了解如何使用fakeroot,请先阅读其它文档。

  1. 你必须了解如何配置内核

使用注意事项

  • 必须在PKGBUILD文件的前10行声明pkgname变量,不要移动它。

如果你事先没有看到这个说明,也不用担心,这不会影响你的软件包,只不过PKGBUILD文件无法自动升级包名称而已。按照这个说明来做,可以使gensync正常工作。

  • 除非你确定你配置的内核能正常工作,否则请使用Arch默认的配置; 运行abs命令,获取kernel26.install文件,然后注释掉install=kernel26.install


# 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 $*


  • 可以通过下面的命令来检查补丁是否设置了EXTRAVERSION
grep +EXTRAVERSION= ./patchname
返回的结果应该类似于:
+EXTRAVERSION = -ck3
如果没有返回该结果,那么可能补丁没有正确设置EXTRAVERSION,你需要使用LOCALVERSION来自定义包名称。
Arch默认的内核会附加-ARCH LOCALVERSION两个变量--你可以把它们设置成任何你喜欢的内容,如-custom (请注意要加前缀-)
在创建过程中会自动更新PKGBUILD中的包名称变量。
  • 如果正确使用当前的PKGBUILD文件,它 应该总是可以根据pkgver、pkgrel、EXTRAVERSION和LOCALVERSION几个变量生成唯一的内核名称,但是最好还是在安装之前仔细检查最终的包名称和内容以防止覆盖。

配置PKGBUILD

将下面的PKGBUILD拷贝到$startdir。PKGBUILD可以从这里下载。在创建之前要记得:

  1. pkgname可以使用默认值,它会被自动设置、校正;
  2. pkgver设置成相应版本号(如:2.6.9);
  3. 按照自己的修订号设置pkgrel。每当你更改内核配置重新创建包时,它都要加1,该包会覆盖前面修订号较低的包。如果你不想让它覆盖原来的内核,而是创建一个平行内核,需要改变LOCALVERSION来创建一个唯一的包;
  4. pkgdesc中加入对修改内容的描述;
  5. 选择合适的镜像地址,添加必要的补丁;
  6. 在{OPTIONAL}中加入补丁指令;
  7. 选择一个合适的配置界面--gconfig (gtk) xconfig (qt) menuconfig (ncurses);
  8. 创建过程中会询问是否make clean --默认值是yes, 如果你不明白这是什么意思,请回答NO
# 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 )

# 从源文件中提取变量
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

  #去掉'i686'中的'i'
  carch=`echo $CARCH | sed 's|i||'`
  cat ../config | sed s|#CARCH#|$carch|g >./.config

  #####加载配置界面--将你喜欢的配置方法反注释掉
  #yes  | make config
  #make oldconfig || return 1
  #make menuconfig
  #make xconfig
  make gconfig

  ##### 请不要修改下面的内容 #####

  # 保存当前包名称
  old_pkgname=$pkgname

  # 设置创建包名称--'''不要'''更改它!
  pkgname=kernel26

  # 保存当前配置文件
  cp ./.config $startdir/config-$(date +%b%d\-%Hh)

  # 从makefile中提取EXTRAVERSION变量,创建唯一的包名称及/usr/src/xxx目录
  _kernextra=$(getvar EXTRAVERSION)
  # 从pkgver中提取版本号--2.6.x.y
  _y=`echo $pkgver | cut --delim . --fields 4`
  # 移除_kernextra中的'.y'后缀
  _kernextra=`echo $_kernextra | sed s|\.$_y||g`

  # 从新的配置文件中读取完整版本号,用于路径名称和包名称
  . ./.config

  # 定制内核,创建唯一的包名称(见下方)
  _kerncust=${_kernextra}${CONFIG_LOCALVERSION}
  # 发行号,与makefile中的相同
  _kernrel=${pkgver}${_kerncust}
  # 从包名称中获取pkgver后缀
  _pkgversuf=`echo $pkgver | sed s|2.6.||g | sed s|\.||g`
  # 设置/boot/下文件名称
  _kernboot=${_pkgversuf}${_kerncust}

  # 根据pkgver和发行号生成新的包名称
  pkgname=${pkgname}${_pkgversuf}${_kerncust}

  # 创建!
  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 $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 \
    $startdir/pkg/usr/src/linux-${_kernrel}/Makefile
  install -D -m644 kernel/Makefile \
    $startdir/pkg/usr/src/linux-${_kernrel}/kernel/Makefile
  install -D -m644 .config \
    $startdir/pkg/usr/src/linux-${_kernrel}/.config
  install -D -m644 .kernelrelease \
    $startdir/pkg/usr/src/linux-${_kernrel}/.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/
  done
  # 拷贝必要的文件,如nvidia,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 \
    $startdir/pkg/usr/src/linux-${_kernrel}/arch/i386/kernel/
  # 拷贝kconfig文件内容
  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
  done
  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)

  # 修正PKGBUILD中的pkgname--这可以让gensync正常工作
  # 注意:pkgname变量必须在PKGBUILD文件的前10行声明!
  cd $startdir
  sed -i 1,11 s|pkgname=$old_pkgname|pkgname=$pkgname| ./PKGBUILD
}
# vim:syntax=sh
  • 安装新的内核

config文件

请注意:在创建过程中,最终的内核配置文件保存在$startdir下面,文件名类似于config-Apr13-12h,原来的配置文件仍然为config。如果你想重复利用配置文件,请注意正确的配置文件位置。

更新启动引导器

  • 编辑LILOGRUB的配置文件,加入新的启动项。新的内核被安装到与原内核相同的位置。强烈建议你保留原有内核及其启动项,直到确认新内核正常工作时再将其移除。
  • 如果你使用lilo,记得运行lilo命令进行更新。

其它版本

这个PKGBUILD文件有几个不同的版本,它们的结果差不多,只是结构有所不同:

  • patch - 包含旧的patch=变量
  • verbose - 在创建过程开始前提供包信息以供检查(如上所述)
  • buildstats - 与前面一个相似,不过提供更详细的信息,并永久保存。

我想要Arch的logo!

logo_linux_clut224.ppm/var/abs/core/base/kernel26拷贝到$startdir,然后把logo_linux_clut224.ppm添加到source变量。然后在PKGBUILD文件对应的位置加入以下内容(>>后面的内容):

   ##### 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

在编译内核过程中打开以下选项:

#
# Logo configuration
#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y

自定义及高级用法(普通用户请勿轻易尝试)

有些用户成功地根据自己的需要以这个PKGBUILD为基础进行了自定义,有些人则根据其原理发展出一套新的方法。如果需要创建多个相同版本的内核,建议利用sed命令自动设置config文件中的CONFIG_LOCALVERSION变量,根据日期、主机名等。 例如

    # 去掉'i686'中的'i'
    carch=`echo $CARCH | sed 's|i||'`
    cat ../config | sed s|#CARCH#|$carch|g >./.config

  >>  # 将LOCALVERSION设置成 -date
  >>  sed -i s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%y%m%d`|g ./.config

    #####加载配置界面
    #yes  | make config

或者

    # 将LOCALVERSION设置成 -date-hostname
    sed -i s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%y%m%d`-`hostname`|g ./.config

如果你还担心会发生重复,可以把LOCALVERSION设置成从00:00:00 1970-01-01 UTC到当前所过的秒数!

    sed -i s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=-`date +%s`|g ./.config

问题

如果你在使用上面的verbose PKGBUILD(Other Versions)文件时产生错误的包名称,请在创建之前检查其命名方案--只要在开始创建之前,随时都可以按ctrl+c退出。

反馈

如果你对上面的PKGBUILD文件有任何问题/注解/建议,请加入我们的[讨论]。

我们已经吸收了一些建议,但是请记住KISS哲学,以及我们原来的目标。编译内核是一个充满变数的过程,祝你好运!

DibbleTheWrecker