|
楼主 |
发表于 2008-5-10 09:10:02
|
显示全部楼层
build.sh的操作顺序如下:
1.确认放在$MACHINE里的目标平台的架构(默认和主系统相同),和放在$MACHINE_ARCH里的目标机处理器架构。
2.[译者注3]编译一个主系统的二进制的make并安装到$TOOLDIR/bin/nbmake。
3.创建包含环境变量的make“封装”shell脚本,设定控制编译和安装什么到$TOOLDIR/bin/nbmake-$MACHINE(这也许是buld.sh所要做的最后一个操作)。
4.使用$TOOLDIR/bin下可用的二进制程序,编译主系统工具用以产生目标$MCAHINE的二进制程序并安装到$TOOLDIR。
5.使用$TOOLDIR下的主系统工具执行其余要求的操作,包括:
编译一个NetBSD发行套件到$DESTDIR。
为某个特定的NetBSD版本编译内核和$DESTDIR下所有的包到版本目录$RELEASEDIR。
编译一个特定的内核
从$DESTDIR创建版本的“sets”或是从源码创建源码的“sets”。
从$DESTDIR升级目录(通常是“/”)。
某些$MACHINE平台支持多余一个的$MACHINE_ARCH处理器架构(一个可处于两个尾端模式的处理器或是不止一字大小的处理器认为是不同的处理器架构),并且build.sh支持编译不同处理器架构的作为不同的版本。
5.2.src/BUILDING
build.sh的内建文档。
5.3.src/Makefile
这个源码树顶层目录下的Makefile包含各种易于编译整个NetBSD源码树的目标,包括:
build
编译整个NetBSD系统,为了确保依次编译所依赖的包。
Distribution,buildworld
执行make build接着安装安装完整的发行套件到$DESTDIR,包含$DESTDIR/etc目录$DESTDIR/var目录
release
执行make distribution,接着编译内核,发行媒介,安装“sets”,然后对$RELEASEDIR目录下的系统打包。
installworld
从$DESTDIR目录下安装发行套件到$INSTALLWORLDDIR(通常是“/”。
5.4.src/share/mk
为了简化编译过程,在目录src/share/mk目录下,NetBSD使用了一个make的Makefile包含文件库(以.mk为后缀)。这是从4.3BSD Networking/2和4.4BSD Lite继承而来的,在十年里有了很大的改进。
5.5.src/tools
传统上,BSD系统是由内建的工具,编译器,包含文件和库编译的。这对于交叉编译来说是不行的,这个框架还修正了在第三节提到的很多别的问题。
src/tools包含制作过程中用以编译各种主系统工具的make框架。这些工具由一个autoconf然后编译形式兼容的框架所编译,并且使用复用Makefile到NetBSD源码树的剩余部分以最小化代码复制。
这些主系统工具的源码做过少量修改以使其可编译为NetBSD(目标平台)程序,主系统工具也是这样。
主系统工具安装到$TOOLDIR,对于BSD make, src/share/mk下的“.include”框架先于标准版本来选择各种主系统工具。例如,对于i386目标平台$CC将是$TOOLDIR/bin/i386--netbsd-gcc而不是cc。
除了内建版本的binutils和gcc外,也可以支持使用别的工具链。这对于内建工具链还不支持的目标平台是很有用的。
主系统工具当前包括:
as asn1_compile binutils cap_mkdb cat cksum
compile_et config crunchgen ctags db dbsym
file gcc gencat groff hexdump install
installboot ld lex lint lorder m4 makefs
makewhatis mdsetimage menuc mkcsmapper
mkdep mkdep mkesdb mklocale mktemp msgc
mtree pax pwd_mkdb rpcgen su nlabel texinfo tsort uudecode yacc zic
大多数主系统工具安装时都带“nb”前缀,以和主系统上类似名字的程序相区别。GNU工具链程序是例外的,它们已经有了例如i386—netbsdelf-gcc这样的名字了。
5.6元逻辑支持
传统上,install是由root来运行的,以相应的属主和权限安装到$DESTDIR(通常是“/”)的相应目录里。
这阻止了非root用户编译整个发行套件,因为很多文件要求特定的权限,例如对/usr/bin/su设置set-user-ID。
为了解决这个问题,为了使存在的mtree工具支持全路径名(对比于上下文相关的想对路径),我们提升了相关文件,并把最终结果称为“元逻辑”记录。一个记录的例子是:
./usr/bin/su type=file mode=04555 \
uname=root gname=wheel \
time=1057493599.102665
对于每个给定的编译,都要创建一个元逻辑,对于每个安装路径都有一个“元逻辑”行。元逻辑文件由编译全过程中的各种工具操控和分析。
install改成可以安装到当前用户的路径里而不需要特殊权限,并取代了相应于元逻辑的要求权限。src/share/mk下的“.mk”文件和少量的特定情形的Makefile需要修改来利用install的这个功能。
pax修改成可以分析用于要添加到列表的元逻辑,甚至可以为$DESTDIR下还没创建的设备添加伪入口。这用于制作由非特权用户由元逻辑和$DESTDIR制作的包含正确的属主和权限的tar.gz文件。这个脚本创建用于分析元逻辑的和引用适当的pax的“安装集”。
5.7.makefs
各种平台使用发行媒介要求从ffs文件系统引导。之前,NetBSD使用“回环虚拟节点磁盘驱动”(vnd),但这在很多别的系统上无法使用,并且挂载和写都要求root权限。
添加了makefs来从一个目录树创建文件系统映象,也可选元逻辑。从概念上来看这类似于mkisofs-一个可创建iso-9660文件系统映象的GPL程序。
使用makefs,一个非特权的用户可以创建带有完整设备节点(随后由元逻辑指定)的ffs文件系统。
同时makefs以一种易于添加别的文件系统支持的方式写就,当前只支持ffs文件系统(包含大尾端和小尾端,因为NetBSD ffs代码支持对立尾端的ffs文件系统,可参考内核的“FFS_EI”选项,在应用程序工具里也支持例如newfs和fsck_ffs).对于例如iso9660,ext2fs和FAT的支持也在考虑之中,但此时并不是一个高优先级的事情。
ffs后端的实现重用了一定量的NetBSD内核当前的ffs实现(在src/sys/ufs/ffs)代码,但是坦率的讲,块分配的代码是以类似的方式重新实现的。在这部分做了很多假定,例如块不需要重分配,
因为所有文件和目录(也作为文件)的大小在创建文件系统的时候是已知的。
ffs在集成到4.2BSD之前是以用户程序实现的,在经过20多年的内核磨砺,已经和缓冲cache以及其他内核子系统紧紧联系在一起,这使它很难以一个单独的程序使用。
5.8.installboot
大多数平台需要发行媒介上有引导块,这是由installboot安装的。之前,每个平台在/usr/mdec/installboot都有它自己版本的installboot,是作为内核源码的一部分编译的,它严重依赖于内核源码。也要求root权限并通常要求内核支持特定的磁盘标识ioctl()的并只在实际的磁盘设备上工作。
/usr/sbin/installboot是取代机器相关版installboot的。它可在文件系统映象上工作,也不需要root权限或是内核支持ioctl()的来作那些。尽管不同硬件平台的实际实现显然是不同的,各种平台间的引导块设计因此实现标准化。
NetBSD-1.6方出的所有平台的二进制版本都使用了这个结构(除了i386)。由于它的installboot的怪异的实现,因此i386是个特例,但是由于为i386交叉编译的主机是个双核i386机器,它可在本地运行工具。在NetBSD-current已经消除了这个问题。
与此相关的是,可以制作在多平台上引导NetBSD的光盘。例如,i386,sparc64和macppc可以从相同的磁盘引导,对于别的平台还有广阔的空间。NetBSD-1.6放出了39个平台的伙同源码的二进制版本,装上4个CD可引导9个平台的。
5.9.src/etc/postinstall
postinstall是个脚本,在NetBSD放出后有边时,它检验和/或修正配置变更。
postinstall添加到编译系统来探测,大多数情况下,自动修复,由软件更改造成的配置变化。
Postinstall支持的测试是:
postinstall
/etc/postinstall保持最新
defaults
/etc/defaults保持最新
mtree
/tec/mtree保持最新
gid
/etc/group包含要求的组
uid
/etc/passwd包含要求的用户
periodic
/etc/{daily,wekkly,monthly,security}保持最新
rc
/etc/rc*和/etc/rc.d保持最新
ssh
ssh和sshd配置升级
wscons
wscons配置文件升级
makedev
/dev/MAKEDEV保持最新
postfix
/etc/postfix保持最新
obsolete
obsolete文件集
sendmail
sendmail配置保持最新
6.未来的工作
6.1.xsrc
NetBSD当前不支持交叉编译“xsrc”(我们对X11R6/XFree86 4.x的复制),但最终会修正这个。XFree86 4.3自己添加了交叉编译支持。为了和我我们的编译系统集成,我们也许会对X11实现自己的交叉编译方法。XFree86的交叉编译方法不能满足我们的所有需求,特别是移除对root权限的要求。
6.2pkgsrc
“pkgsrc”(NetBSD的包管理系统)不能交叉编译。一小部分特别,通常很小的包很易于交叉编译,但大部分需要大量的努力才信。
有两个解决这个问题简易方法的建议:
1.Krister Walfridsson建议在模拟器里本地编译这些包,使用最优化的方法,例如直模拟用户模式,并找准系统需求和在本地运行(手动调整参数)。
一个增强的版本是探测模拟的程序是否是gcc(打个比方),在这种情况下调用系统本地的交叉编译器。
初步的进展看起来是很有前景的,使用ARM模拟器,编译速度是在ARM上本地编译的6倍。
这个建议会被用于解决6.1节所提出的“xsrc”的问题。
2.使用distcc[8]这样的工具来使用远程系统(更快的)分布式编译C或C++代码,甚至是可用和你当前系统的架构不同[译者注4],只要有合适的编译器可用。这仍然要求本地系统参与部分编译过程[译者注5]。
7.结论
build.sh对于各种问题是个很好的解决办法。现在在运行旧版本的NetBSD上很容易编译着整个NetBSD发行套件,甚至可在别的系统例如Darwin/MacOSX,FreeBSD,Linux和Solaris上编译。
总体说来,NetBSD里使用build.sh的支持问题比以前少多了,特别是考虑到现在支持的平台数。过去,在完成剩余的编译前,以一个特定的顺序(经常改变的)升级各种内建的工具,包含文件和库。
现在,一个完整的编译过程不会对运行心痛造成任何影响,当完成一个编译时候,升级也很容易成行。
作者通常在我们(很快的)alpha,i386,macppc和sparc64系统上使用build.sh来为例如alpha,i386,mappc,pmax,shark,sparc,sparc64和vax来交叉编译整个发行版,以一个非特权用户使用只读源码。
鸣谢
Todd Vierling写了最初版本的build.sh,并设定了src/tools的框架。
Jason Thorpe做了很多工具链方面的工作,并且组织了build.sh的框架结构。
Erik Berls写了并维护了用于NetBSD版本引擎机器的用于在多个编译机器上为多个目标平台自动编译多个版本分支发行套件的autobuild脚本。
Wasabi系统有限公司。为这个从事这个项目各种开发工作的很多人员付薪水。
自由软件基金会提供了了GNU工具链,它的移植性是相当棒并且是交叉编译友好的。
参考
[1]欢迎到NetBSD项目
http://www.NetBSD.org
[2]NetBSD项目Autobuild[用于NetBSD 1.6]
http://releng.NetBSD.org/ab/B_netbsd-1-6
[3]可移植性和硬件支持平台
http://www.NetBSD.org/Goals/portability.html
[4]Frank vander Linden,移植NetBSD到AMD x86-64:操作系统移植性的实例研究,BSDCon 2002
http://www.usenix.org/events/bsd ... /linden/linden_html
[5]Jason R.Thorpe,用于NetBSD的一个机器不相关的DMA框架,Usenix 1998年年刊技术参考
http://www.usenix.org/publicatio ... eenix/thorpe.dma.ps
[6]欢迎到GCC主页
http://gcc.gnu.org
[7]包:fakeroot 0.4.4-9.2
http://packages.debian.org/stable/utils/fakeroot.html
[8]distcc:快速,自由的分布式C/C++编译器
http://distcc.samba.org
[译者注1]关于交叉编译的原理和方法可以参见LFS的CLFS子项目,常见的两种方法是clfs-1.x,clfs-sysroot,一些原理分析可参见linuxsir.cn的LFS讨论区一些精华帖。还有一个材料是Cygnus的文档《The GNU configure and build system》,对于交叉编译的原理有讲解。还有一些就不一一列出,注释只是提示性的,对交叉编译不了解的也许会有帮助。
[译者注2]这里的意思应该是把make参数定义成一个变量就不用每次都指定了,封装的目的是为了使用正确的参数,一般是个简单的shell脚本,例如Gentoo distcc交叉编译文档里gcc封装就是指定使用交叉编译器而不是本地编译器,可参见Gentoo文档库,如果不想看英文的,可参见我翻译的Gentoo distcc文档和distcc交叉编译文档。
[译者注3]build.sh每次总是首先重新编译nbmake。这在NetBSD FAQ的《Tracking NetBSD-current》这篇文章的最后有解释:
甚至在运行./build.sh tools和使用-u标识或是在/etc/ma.conf里指定TOOLDIR,build.sh总是重新编译nbmake。这是正常的,原因可在build.sh本身里找到,在rebuildmake函数里:
# 注意如果TOOLDIR已经在"mk.conf"里设定好了, #我们并不会倾向于从其中读取TOOLDIR,
#因为它可能包含make变量扩展和别的仅在我们有 #个可工作的${toolprefix}make后才可用的内容。
#所以这个逻辑只在用户在环境变量里设置TOOLDIR #或是对build.sh使用-T选现。
所以,如果你不想重编译nbmake,你需要使用-T指定工具目录或是设置TOOLDIR环境变量。
[译者注4]如果不想看英文的,可以参见我翻译的Gentoo distcc/distcc交叉编译文档。
[译者注5]你可以不用你的机器而把编译任务全分配到别的你用于编译的机器上。 |
|