从ABS定制内核 (简体中文)
From ArchWiki
i18n |
---|
English |
简体中文 |
这一篇翻译得比较吃力,哪位大侠帮着校正一下吧:英文原文。
Contents |
介绍
你可以通过传统方法或者ABS来编译自定义内核。一小部分Arch用户更喜欢前一种方法,但是ABS更加自动化。两种方法没有本质上的优劣,使用哪种方法完全是你自己的选择。
我们将会给出一个有效地可以用来创建自定义内核的PKGBUILD文件,理想情况下你只需要按照自己的条件填写一些变量就可以创建自己的内核。PKGBUILD文件自动解决EXTRAVERSION
和LOCALVERSION
。前者一般表示主补丁代号(如-ck,-nitro);后者用来自定义内核名称。建议简单地把LOCALVERSION
设为-custom
或创建日期(如-20050105
)。唯一的LOCALVERSION
可以保证生成唯一的内核包。
哲学与逻辑(知其然,并知其所以然)
- Arch之道 - KISS
- 该PKGBUILD基于以前被广泛接受的版本
- 该文件使用简单、合理的命名方案,只使用ABS系统及内核编译过程所需的变量:
- Arch官方内核包一般命名为
kernel26
,我们根据内核版本2.6.x或2.6.x.y将包名称记为kernel2611
或kernel26117
生成的内核镜像文件名类似于vmlinux26
或vmlinuz26117
; - 在内核编译过程中,从
Makefile
中提取EXTRAVERSION
,从内核配置文件(.config)中提取CONFIG_LOCALVERSION
,与内核版本(2.6.x)组合在一起形成新的内核版本:
- Arch官方内核包一般命名为
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
,pkgrel
,pkgdesc
,并添加额外的源,把补丁加入source
数组。在指定的位置加入补丁命令,选择是否make clean
。剩下的步骤都是自动完成的。 - 创建了自定义命名方案后,PKGBUILD会自动根据新的
pkgname
修正/升级,并允许简单的gensync
操作。
注意
- 该PKGBUILD文件只适合于创建2.6内核包;
- 你需要具备利用ABS系统创建软件包的知识。可以参考ABS - The Arch Build System, The Arch package making HOW-TO - with guidelines and Patching in ABS
我建议你不要拿内核作为你ABS的第一个实验品。如果你想了解如何使用fakeroot
,请先阅读其它文档。
- 你必须了解如何配置内核
使用注意事项
- 必须在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可以从这里下载。在创建之前要记得:
-
pkgname
可以使用默认值,它会被自动设置、校正; - 将
pkgver
设置成相应版本号(如:2.6.9
); - 按照自己的修订号设置
pkgrel
。每当你更改内核配置重新创建包时,它都要加1,该包会覆盖前面修订号较低的包。如果你不想让它覆盖原来的内核,而是创建一个平行内核,需要改变LOCALVERSION
来创建一个唯一的包; - 在
pkgdesc
中加入对修改内容的描述; - 选择合适的镜像地址,添加必要的补丁;
- 在{OPTIONAL}中加入补丁指令;
- 选择一个合适的配置界面--gconfig (gtk) xconfig (qt) menuconfig (ncurses);
- 创建过程中会询问是否
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。如果你想重复利用配置文件,请注意正确的配置文件位置。
更新启动引导器
- 如果你使用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