ABS - the Arch Build System(已译)这篇文章是一篇很好的关于建立或修改Arch Linux软件包所需的工具和文件的概述。如果你想自己建立或重新编译软件包,这差不多就是你所需知道的一切了。但无论如何,如果你想自己建立一个新的软件包,这儿还有一些额外的指导方针你需要知道。本文假设你已读过并理解了ABS的相关描述。
你将建立一个软件包所需的所有信息保存在PKGBUILD文件中。当你运行makepkg时,它将在当前工作目录中查找PKGBUILD文件,根据其中的指令编译软件。在成功完成编译后,二进制文件及一些信息,如包的版本、依赖关系等都被压缩存放在名如name.pkg.tar.gz的软件包中。这个包可以用pacman -Up 来干净地安装。
PKGBUILD文件包含了建立软件包所需的全部指令,从形式上说,BASH可以直接解释这些指令(别担心,这些小线索有用)。这些变量的含义已在ABS - the Arch Build System一文中解释过了,但更重要的、易混淆的将在此再次说明。在建立新的软件包之前,你需要建立一个空的工作目录,建议这样命名:/var/abs/local/。这样可以完美地融入标准ABS树,但又不会在你同步ABS树被CVSUP所改动。进入此目录,并建立一个PKGBUILD文件——或者从/var/abs/PKGBUILD.proto拷贝一个模板,或者从其他包中拷贝该文件。当你只是想修改、补充几个选项而不是建立一个全新的文件时,后者显然有用得多。不管怎样,现在你需要一个PKGBUILD文件。
现在,打开这个文件,根据你要建立的包设置这些变量的值:
pkgname
将此变量设置成软件包的名称。不能包含连字符,即“-”,但你可以用下划线代替。习惯上都是用小写字母来命名。并不强求如此,但这样做有好处。软件包的名称与你的工作目录名相同,并且与你要下载的包含的软件源代码的tar.gz文件名也相同。
pkgver
将此变量设置成软件包的版本。可以包括字母、数字及句点。它依赖于你要打包的软件的版本体系(major.minor.bugfix, major.date等)。而且你应该紧跟其源码文件包中的版本号,以使下一步工作更轻松且更灵活。
pkgrel
此变量初始值应为1,且随每次发布软件包而递增。目的是为了区分连续发布的同版本的软件包。有时,第一次发布的软件包有问题或缺少某一功能,当你做好第二个发布版时,你应该将pkgrel加1,这样,pacman就知道需要重新安装此包。当新版本(不是发布号)的软件包发布时,你应该将pkgrel重新设为1。
depends
此变量通常包含一组以空格分开的软件包名,在安装该包之前,应先安装这一组软件包。软件包名也可以放在单引号里,以避免可能产生的shell引用问题。而这一组软件包名应以圆括号括起来。有的程序需要“最低版本支持”,如果那样的话,你应该想使用数学符号“大于或等于”,并将整个条件用引号引起来。举个例子,该包需要glibc包,而且slang库不能低于1.8.0版:depends=('glibc' 'slang>=1.8.0')
source
此变量应包括一组建立软件包所需的文件名,并且至少包含软件源代码的位置——很多都是用双引号引起来的完整的HTTP或FTP定位。PKGBUILD文件的模板显示了如何有效使用先前定义的pkgname、pkgver。如果你需要的文件不能从网上下载,例如,自己做的patch,你可以将这些文件放入PKGBUILD所在目录,然后在此处加上文件名即可。所有加在这儿的路径都是相对路径——相对于PKGBUILD的所在目录。在正式建立软件包之前,这儿所提到的文件都要被下载下来或检查是否存在,如果有任何一个文件不存在,makepkg是不会进行处理的。
md5sums
一组源文件的md5校验和——放在引号内,以空格分开。所有source中的文件,其md5 hash值将自动生成并与该组中的值相比较,顺序与source中的一样。源文件本身的顺序并不重要,重要的是其md5sums的顺序——makepkg并不会去猜哪个md5sum是哪个源文件的,当出现不符量,它只会给出错误信息。在source设好后,在PKGBULID所在的目录中,你可以很轻松地用makepkg -g产生这一组md5sum。makepkg -g >> PKGBUILD会将产生的md5sums追加在PKGBUILD文件末尾,你可以将最后的几行移动到文件的适当位置。
现在,你已设好了软件的一些信息——哪儿能下到源文件,包的名称是什么等等。下一步就是如何写出指令去编译、安装你想要打包的程序。一般来讲,在你开始自动打包处理之前,你至少要手动做一次,除非,你很清楚在此之前你所做的一切。但不管怎样你都应该首先说读读这个。很不幸的是,尽管很多程序都可以以“三步曲”——"./configure; make; make install"来安装,但这不是万能的。如果你必须要打补丁才能使之正常工作的话,你的包将变得很丑陋。单凭经验的方法:如果你不能从源码编译程序并将其安装到一个指定的临时子目录下的话,就别去尝试打包了。makepkg中没有能帮你解决源码问题的魔法小精灵。
也就是说,你应该下载源码包,解压,记下所有有关编译、安装的命令。PKGBUILD文件中的build函数将精确地重复这一步骤,并在编译完成后将一切捆在一起。
现在你可能需要编辑build函数。其实,它用的只是普通的shell命令——遵循bash语法。该函数的基本目的就是自动编译好程序,并且将其安装到新建的软件包目录,使makepkg可以轻松地打包,而不是要将所需的文件从你的系统中一个一个地找出来。
一般来说,build函数的第一步就是进入源文件解压后生成的目录。你可以使用$startdir——它代表PKGBUILD所在的目录。你也可以使用之前设置的$pkgname和$pkgver变量。例如,根据makepkg解压生成的目录,build函数的第一个命令可能就是cd $startdir/src/$pkgname-$pkgver,通常都会是这样,除非程序的作者是一个非常非常古怪的人。
编译程序就比较难一点了。我想,你应该设法手工编译。因为你不大可能将所有可能需要的步骤都包括进来。这就是希望程序的作者写README和INSTALL文件的原因。
现在,你就在这个目录中,你需要给出命令以编译程序。简单时,你只要使用./configure; make,尽管有很多变化——包括ant build或具体的编译软件的gcc命令。简单地说,软件可能不是以源码形式发布,而你必须用sh installer.run的形式运行。你可能需要多研究一下(读README,INSTALL,手册页,可能还要看一看如gentoo的ebuilds,甚至是MAKEFILE或源代码),使其可以正常使用。在某些极端情况下,你可能要修改源代码才能使之正常工作。不管怎样,makepkg需要完全独立地工作——不需要用户的输入。因此,如果你需要编辑Makefile,你应该自己做一个patch,并写在build函数中。或者你必须在build函数中加上sed命令。
好的一面就是,如果你已手动编译了整个软件,你只需将你所用的命令列下来就OK了。由于很多软件倾向于安装在/usr/local中,但Archlinux习惯上将软件安装在/usr中,你应该传递相应参数至configure或make命令,仔细一点。PKGBUILD的模板提供了这样的一个例子。 这可能与你的实际情况有点差异,但不管怎样,你还有一些工作要做。
build函数的下一步工作就是将已编译好的文件放在一个目录中,以方便makepkg将他们打包。这个目录就是pkg目录,它将被软件的安装进程当成你的系统的根目录。所有将被安装进你的系统的根目录的文件,实际上都会安装在pkg目录中的相同的目录结构中(也就是说,你如果要将myprog这个文件安装到/usr/bin中,它实际上是被安装到$startdir/pkg/usr/bin)。幸运的是,只有一小部分软件需要用户手工拷贝大量文件,但他们也提供某些安装程序来自动完成这一工作——通常都是通过调用"make install"来实现。这很危险,但不管怎样,你会发现如何告知安装进程不要将文件安装到系统的根目录,而是安装到$startdir/pkg。否则,你将发现,最终你得到的只是一空的软件包,而你所要打包的文件已“正确地”安装到了你的系统中。很多时候,你都必须像模板文件中那样在调用"make install"时,加上prefix参数。但这也很可能使程序以完全不同的途径来打包,下面还有一些提示:
a.有时,configure脚本接受prefix参数——用来告知将文件安装在何处。例如,你会看到这样的配置:./configure --prefix=$startdir/pkg/usr。
b.有时,可以传递PREFIX选项给make install命令。这种情况下,有时是设置变量,有时是嵌入命令中。更糟的是,你可能必须编辑Makefile(如果软件使用ant的话,就要编辑ant build/properties)。可以使用sed或自己制作补丁。
c.可能也有允许指定安装目录的安装脚本存在。
d.还有一些软件是可以在单独一个目录中运行的。这时只需将其简单地拷入$startdir/pkg/opt即可。
就像你可能猜想的那样,你所知道的与你的经验是必不可少的。特别是在你浏览ABS树内的PKGBUILD文件时,这些知识与经验会很用的,因为有些文件是测试用的,其中可能包括一些有用的小窍门或是恶作剧。
安装程序时常会很小心地在pkg目录下建立子目录,如果它没有建立相应的子目录,你就会在安装过程中收到许多诸如文件拷贝到不存在的子目录中的错误信息。如果那样的话,在运行安装程序之前,你应该在build函数中加入相应的mkdir命令。实际的目录结构是和软件包相关的,有些程序需要将文件拷入/etc或/usr,有些可能需要使用/bin或/opt。大多数的软件需要建立数个目录,你可以使用mkdir -p $startdir/pkg/OTHER/DIRS/AS/NEEDED,“OTHER/DIRS/AS/NEEDED”代表系统根目录下的目录结构。
当你开始写PKGBUILD文件中的build函数时,你需要不停地测试以排除bug。你可以在PKGBUILD所在的目录中运行makepkg来测试。通过一个适当格式的PKGBUILD,很容易就可以创建一个软件包。但如果使用坏掉的或未完成的,这将导致错误。希望这仅仅是个描述性的错误!
如果makepkg成功运行完成,它将在你的工作目录中产生一个新得有点闪闪发亮的名为$pkgname-$pkgver.pkg.tar.gz文件。这是一个pacman可安装的软件包,可以通过pacman -U 或pacman -A 来安装或更新,也可以加入到本地或远程的软件包库中。注意,这只意味着软件包已建立,并不意味着它一定可用!如果你不恰当地使用了prefix参数,包中可能只包含目录结构而没有一个文件!你可以使用pacman的查询功能,显示出其中包含的文件清单及其依赖关系,并可与你认为正确的相比较。"pacman -Qlp "和"pacman -Qip "可以完成这个工作。
如果包看起来很正常,那就是你所要做的。不管怎样,如果你决定发布软件包或PKGBUILD,你应该强制你自己检查、再检查、再再检查其内容及依赖关系。检查时,应列出所有你的软件包所依赖的包的列表。但depends中只需列出第一层依赖关系即可。这就是说你不必在软件包把所有依赖的包都列进去。如果你的软件所依赖的包中已列出了它所依赖的包——尽管这个包你也需要,但你不必在你的软件包中列出来。
例如,gtk2依赖于glib2。列出所有需要的开源C程序,你会发现,gtk2出需要glibc。但glibc不必出现在gtk2的依赖包的名单中,因为glibc是glib2的依赖包,而glib2已经列在gtk2的依赖包的名单中了。
有很多工具可用来检查依赖关系,其中就包括Jason Chu的大名鼎鼎的namcap(在线安装:pacman -Sy namcap),还有神秘的ldd。读一读这些程序的手册页及本文结尾处的链接。你应该通读程序的文档及其WEB页(仔细的开发者会提供“dependencies”说明,这会很有帮助的)。
同时也要保证软件包可以完美地运行!发布一个包含所有必需文件的包,但因为其中隐蔽的选项不能很好地工作,这确实是一件令人恼火的事!但如果你只是自编自用,你完全不必太过担心质量保证这一步,因为只有你一个需要忍受其中的错误。
总结:
1. 下载你想打包的程序的源码
2. 尝试将其安装到指定的目录
3. 将/var/abs/PKGBUILD.proto拷入临时工作目录并改名为PKGBUILD
4. 根据你的需要编辑PKGBUILD
5. 运行makepkg,并检查生成的包是否正确
6. 如果软件包有问题,重复最后两步
更多信息参见以下链接:# makepkg man page(http://www.archlinux.org/pacman/makepkg.8.html)# guidelines(http://www.archlinux.org/docs/en/guide/install/arch-install-guide.html#SEC5.4)# link in the faq(http://www.archlinux.org/docs/en/faq/general/arch-general-faq.html#SECTION00062000000000000000)# about dependencies(http://bbs.archlinux.org/viewtopic.php?t=4)# makepkg tutorial(http://bbs.archlinux.org/viewtopic.php?t=1590)# ABS - the Arch Build System(http://wiki.archlinux.org/index.php/ABS%20-%20the%20Arch%20Build%20System)