LinuxSir.Org  
| 网站首页 | 注册账号 | 论坛帮助 |

欢迎来到LinuxSir.Org!
您还未登录,请登录后查看论坛,或者点击论坛上方的注册链接注册新账号。


发表新主题 回复
精华主题  
主题工具
旧 08-02-29, 19:19 第 1 帖
csfrank 帅哥
 
csfrank 的头像
 
 
注册会员  
  注册日期: Jun 2005
  我的住址: 上海
  帖子: 501
  精华: 20
 

标题: [LFS实战]DIY一个实用的mini-LAPP服务器(Apache PHP PostgreSQL OpenSSH Iptables)


由于论坛排版效果不理想,而且我也只在我的个人空间对文章进行后继更新,所以建议直接到我的空间查看:
DIY一个实用的 miniLAPP 服务器 [x86版]

http://lamp.linux.gov.cn/miniLAPP/LAPP-x86.html
-------------------------------------------------------------------------------
版权声明
本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布。任何人都可以自由使用、转载、复制和再分发,但必须保留作者署名,亦不得对声明中的任何条款作任何形式的修改,也不得附加任何其它条件。您可以自由链接、下载、传播此文档,但前提是必须保证全文完整转载,包括完整的版权信息和作译者声明。

其他作品
本文作者十分愿意与他人共享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有作品的列表:
金步国作品列表

BUG报告,切磋与探讨
由于作者水平有限,因此不能保证作品内容准确无误,请在阅读中自行鉴别。如果你发现了作品中的错误,请您来信指出,哪怕是错别字也好,任何提高作品质量的建议我都将虚心接纳。如果你愿意就作品中的相关内容与我进行进一步切磋与探讨,也欢迎你与我联系。联系方式:Email: csfrank@citiz.net ; QQ: 70171448 ; MSN: csfrank122@hotmail.com

==============================================

先决条件
本文的读者应当至少手动安装过一次 LFS ,如果你没有做过 LFS ,这篇文章很可能不适合你,请先按照《Linux彻底定制指南》做一遍 LFS 。另外,如果你对编译优化也很感兴趣,那么《GCC编译优化指南》也很值得一读。

目标
youbest兄的大作《5M大小的Apache服务器》和其续篇《600K的Apache服务器》将LFS的精神发挥到了极致,令人叹为观止!然而许多实用主义者(包括我在内)也只能叹为观止而已,因为这样的服务器由于过分追求小巧而变得不太实用,基本上不能在实践中用于生产目的。

鉴于上述原因,本文打算制作一个既实用又小巧的 Linux + Apache + PHP + PostgreSQL + OpenSSH + Iptables 服务器,并且实用优先于小巧。尽管实用优先于小巧,但是与基于普通发行版搭建的LAPP服务器相比仍然相当Mini(本文制作出来的最终系统核心部分大约 15MB[其中体积较大的文件有:bzImage约1MB、postgres约3.5MB、libphp5.so约4.6MB、libc.so约 1.3MB、libcrypto.so约1.1MB],总体积大约150MB),因此我把它称为"miniLAPP"服务器。当然,除了小巧,灵活和高效也重要,这在本文中主要体现在:㈠对软件包进行最大限度的自定义配置,㈡在保证稳定的前提下进行编译优化。

为了避免纠缠于各种复杂的硬件环境(它不是重点所在),本文将在 VMware Workstation 5.5.5 上建立一个虚拟机。具体如下:Intel 440BX 主板,athlon-xp处理器(如果你的CPU与我不同,那么只要将本文中所有的"athlon-xp"都替换成你的CPU型号即可,具体可以参考Gentoo Safe Cflags),512M内存(最低384MB),100M网卡(PCnet32),4G硬盘(BusLogic SCSI 0:0),CDROM(IDE 1:0 lfslivecd-x86-6.3-r2160-min.iso 仅供安装)。

网络环境:ip:192.168.10.33/24 ,broadcast:192.168.10.255 ,gateway:192.168.10.250 ,没有DNS 。如果你的环境与此不同,请自行调整相应的ip命令。

思路
基本上,小巧和实用是有冲突的,因为越要求实用就越需要各种功能,也就越无法保证小巧。为了解决这个问题,本文采用了"核心+扩展"的思路。所谓" 核心"是指保证服务器正常运行必须使用的资源,比如:libc, init, httpd, postgres, libphp, sshd ... 以及各种设备文件、配置文件等等。所谓"扩展"是指非运行时必须的资源,比如:top, cat, gcc ... 等等,主要用于服务器维护。

解决方案是将"核心"部分安装在"/"目录下,使其在服务器一起动的时候就能够使用,而将"扩展"部分安装在"/usr"目录下,并且"/usr"位于独立的分区上,仅在需要使用的时候才手动挂载,使用完毕以后再手动卸载。

事实上,对于绝大多数软件包而言,所需要的只是其中的一小部分而已,因此,绝大部分软件包的主体都位于"/usr"目录下,仅将必须的某些部分安装到"/"下。

另一个问题是使用静态连接还是使用动态共享库?从小巧的目标来看,似乎应当使用静态连接,但是考虑到:

1. 追求小巧并非第一重要,此处"Mini"的含义并非偏重于磁盘空间,而是尽可能减少不必要的程序和组件。
2. 动态连接的程序可以在内存**享库文件,而静态连接的程序则无法实现。考虑到此服务器可能扩展为提供 DNS, FTP, Mail, Proxy 等其它服务,静态连接将导致运行时占用更多的内存。

因此本文决定采用常规的动态连接。更多关于静态连接的害处,可以参考"Static Linking Considered Harmful"一文。

制作工具链前的准备工作
使用 LiveCD 开机,直接按回车键启动,所有设置均采用默认。
如果希望使用ssh进行远程安装,请执行如下步骤:
代码:
passwd ...... net-setup ...... /etc/rc.d/init.d/sshd start
磁盘分区与格式化(使用cfdisk的具体操作就不详细说明了,这里只给出结果):
代码:
/dev/sda1 ext2 /boot 10MB /dev/sda2 xfs / 50MB /dev/sda3 xfs none 50MB [将来升级的备用根目录] /dev/sda5 xfs /usr 300MB /dev/sda6 xfs /root 300MB [借用为 DESTDIR 父目录,也为将来升级的备用usr目录] /dev/sda7 xfs /var 200MB /dev/sda8 xfs /www 200MB [ WEB 目录,借用存放临时工具链] /dev/sda9 xfs /data 剩余 [数据库目录,借用存放源代码和编译目录]
代码:
mke2fs -q -T news /dev/sda1 && mkfs.xfs -f -q /dev/sda2 && mkfs.xfs -f -q /dev/sda3 && mkfs.xfs -f -q /dev/sda5 && mkfs.xfs -f -q /dev/sda6 && mkfs.xfs -f -q /dev/sda7 && mkfs.xfs -f -q /dev/sda8 && mkfs.xfs -f -q /dev/sda9 &&
制作工具链之前的准备工作(省略了软件包和补丁的下载命令)。
[提示]如果在工具链的制作过程中中途关机,那么只需在重新开机后重新执行下面的命令即可恢复工作状态。不过,关机前一定要运行"sync"命令并 umount所有挂载点,否则可能出现意外。 [说明]为了binutils-pass2测试成功,这里使用了一个rm废除LiveCD的g++和cpp,否则ld测试可能会失败。不过,没有C++编译器将会导致Glibc的 bug-atexit3-lib.os tst-cancel24.o c++-types-check 测试失败,并且无法运行dejagnu的测试程序。
代码:
rm -fr /usr/bin/*{c,g}++ /usr/include/c++ /usr/lib/lib{stdc++,supc++}.* /usr/lib/gcc/*/*/cc1plus /lib/cpp /usr/bin/cpp && export LFS=/mnt/lfs && mkdir -p $LFS && mount -t xfs /dev/sda2 $LFS && mkdir -p $LFS/boot && mount -t ext2 /dev/sda1 $LFS/boot && mkdir -p $LFS/usr && mount -t xfs /dev/sda5 $LFS/usr && mkdir -p $LFS/root && mount -t xfs /dev/sda6 $LFS/root && mkdir -p $LFS/var && mount -t xfs /dev/sda7 $LFS/var && mkdir -p $LFS/www && mount -t xfs /dev/sda8 $LFS/www && mkdir -p $LFS/data && mount -t xfs /dev/sda9 $LFS/data && # 这里省略了下载软件包和补丁的命令 ln -sf $LFS/www / && echo 'exec env -i HOME=$HOME TERM=$TERM PS1="\\u:\\w\\\$ " /bin/bash' > ~/.bash_profile && echo "set +h umask 022 export LFS=$LFS export SRC=$LFS/data export PATH=/www/bin:/bin:/usr/bin export LC_ALL=C TZ=UTC export CFLAGS='-DNDEBUG -O3 -finline-limit=200 -fomit-frame-pointer -pipe -fno-bounds-check -freg-struct-return -march=athlon-xp' export LDFLAGS='-s -Wl,-O1,-s,--enable-new-dtags,--hash-style=gnu' export kLDFLAGS='-O1 --enable-new-dtags --hash-style=gnu' alias make='make -j1' mkdir='mkdir -p' patch='patch -p1 -i' mv='mv -f' cp='cp -pf' rm='rm -fr' cd \$SRC" > ~/.bashrc && source ~/.bash_profile
为了尽可能使工具链与后面编译的最终系统兼容,这里在工具连阶段就使用相同的优化参数进行编译(pass1例外),不过由于宿主系统的影响,这样做可能会导致很多测试失败,所以工具连阶段仅对Glibc/GCC/Binutils进行测试,并且忽略Glibc/GCC测试错误(只记录测试信息)。 [说明]kLDFLAGS是专供内核使用的连接器参数(直接传递给ld)。

编译过程是一个漫长的冒险,特别是在使用了一大堆configure选项和优化参数的情况下,出现错误是再正常不过的事情了。本文的所有代码都在我的CPU上测试通过,因为我没有更多的CPU,所以无法进行更多的测试,但是一个基本原则就是,一旦遇到编译或测试错误,首先想到的应当就是降低优化级别,看看能不能通过。理论上,将本文所有的"athlon-xp"都替换成"i686",并且设置 CFLAGS="-O2 -fomit-frame-pointer -pipe -march=i686" LDFLAGS="-s" kLDFLAGS="",应当可以在目前实际使用的所有 x86 CPU 上顺利完成。如果降低优化级别仍然不能解决问题,那么可以继续调整configure选项。

下面这些优化选项可能是地雷,尽量不要使用,如果你喜欢冒险,并且不小心踩到了,别怪我没提醒过你.....

CFLAGS
"-D_FILE_OFFSET_BITS=64 -fvisibility=hidden; -malign-double; -mregparm=3; -msseregparm; -ftracer; --param max-gcse-memory=100M; --param max-gcse-passes=3; -Wa,-R; -Wa,-march=athlon"至少会导致Glibc配置或编译失败。"-m128bit-long-double"会导致GCC的 gcc.dg/pr19402-2.c测试失败,Glibc的math/test-misc.out测试失败,autoconf的AC_PROG_SED 测试失败,tar的31/33/35号测试失败。"-freg-struct-return"虽然能让Glibc通过测试但却会间接导致GCC的 gcc.dg/struct-ret-libc.c测试失败,这是二进制兼容性所致,一般可以忽略它。"-ftree-loop-linear"会导致 PostgreSQL无法运行测试程序(无法初始化数据库),还会导致JPEG测试失败。

LDFLAGS
"--as-needed"将导致Glibc的stdlib,nptl,elf测试出现多处错误,"-znow"将导致 Glibc的elf测试出现多处错误。"--sort-common"会导致Automake的ccnoco.test测试失败(直接和间接原因都有??)。

kLDFLAGS
"-s"会导致内核编译失败。

附件为本文所有需要使用的补丁和配置文件
上传的附件
文件类型: zip patchs.zip (120.5 KB, 22 次查看)







__________________
@@

此帖于 08-03-03 11:14 被 csfrank 编辑.
  csfrank 当前离线   回复时引用此帖
旧 08-03-01, 10:46 第 2 帖
youbest
 
youbest 的头像
 
 
版主  
  注册日期: Jan 2005
  帖子: 1,386
  精华: 20
 

确实很长,赞一个!







__________________
青橄榄在入口的时候是苦的,过了一会你就可以长久的品味那淡淡而又清爽的甜味。

青橄榄 http://youbest.cublog.cn

青橄榄计划的第一步总算迈出来了,等待它的是万里长征.

做技术要有做技术的原则,决不拿技术做侵权的事情,更不能用来做违法的事情。工作丢了可以再找一个,原则丢了就找不回来了。
  youbest 当前离线   回复时引用此帖
旧 08-03-01, 11:37 第 3 帖
cbkid
 
cbkid 的头像
 
 
注册会员  
  注册日期: Jul 2007
  帖子: 279
  精华: 2
 

楼主无私奉献,感激。支持







__________________
为了那些爱你的人和你爱的人
无论你多努力都不为过

徐牛
  cbkid 当前离线   回复时引用此帖
旧 08-03-03, 10:05 第 4 帖
csfrank 帅哥
 
csfrank 的头像
 
 
注册会员  
  注册日期: Jun 2005
  我的住址: 上海
  帖子: 501
  精华: 20
 

制作工具链
此处工具链的制作基本上与 LFS 第五章相同,只是增删几个包、改动了一些配置选项、简化了几个包的安装动作、将几个补丁的功能用 sed 进行了替代、以及其它一些小变化等等,因此下面只列出命令而不进行任何说明。
代码:
( test ! -f $SRC/tmp.log ) && [ "`pwd`" = "$SRC" ] && tar -xf binutils-2.18.tar.bz2 && mkdir binutils-build && cd binutils-build && echo 'MAKEINFO = :' >> ../binutils-2.18/Makefile.in && CFLAGS="-O2 -fomit-frame-pointer -pipe -march=athlon-xp" LDFLAGS="-s" \ ../binutils-2.18/configure --prefix=/www --disable-nls --disable-rpath --disable-multilib --disable-shared --enable-static --disable-werror --without-gmp --without-mpfr --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --with-pic && make all install tooldir=/www/ && cp ../binutils-2.18/include/libiberty.h /www/include && make clean-ld all-ld LIB_PATH=/www/lib tooldir=/www/ && cp ld/ld-new /www/bin/ && cd $SRC && rm */ && echo '1-binutils-pass1' >> $SRC/tmp.log && sync && tar -xf gcc-core-4.2.3.tar.bz2 && mkdir gcc-build && cd gcc-build && sed -r -i 's|^LDFLAGS(_FOR_TARGET)? =|& @LDFLAGS@|' ../gcc-4.2.3/Makefile.in && sed -i 's/install_to_$(INSTALL_DEST) //' ../gcc-4.2.3/libiberty/Makefile.in && sed -i -e's@\./fixinc\.sh@-c true@' -e'/^LIBGCC2_DEBUG_CFLAGS/d' ../gcc-4.2.3/gcc/Makefile.in && sed -i '/MULTILIB_OSDIRNAMES/d' ../gcc-4.2.3/gcc/config/i386/t-linux64 && CFLAGS="-O2 -fomit-frame-pointer -pipe -march=athlon-xp" LDFLAGS="-s" \ ../gcc-4.2.3/configure --prefix=/www --with-local-prefix=/www --enable-languages=c --enable-bootstrap --disable-nls --disable-rpath --disable-multilib --enable-shared=libgcc --enable-static=libgcc --disable-libgomp --disable-libmudflap --disable-libssp --enable-linux-futex --enable-threads=posix --enable-tls --disable-symvers --with-as=/www/bin/as --with-ld=/www/bin/ld --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --without-gmp --without-mpfr --without-system-libunwind --without-system-zlib --with-pic --without-x && make bootstrap4 install LIBCFLAGS="-O2 -fomit-frame-pointer -pipe -march=athlon-xp" BOOT_CFLAGS="-O2 -fomit-frame-pointer -pipe -march=athlon-xp" BOOT_LDFLAGS="-s" && ln -sf gcc /www/bin/cc && INC=`gcc -print-file-name=include` && TOL=`gcc -print-file-name=install-tools` && rm $INC/* && cp $TOL/include/* $INC && cp $TOL/gsyslimits.h $INC/syslimits.h && unset INC TOL && cd $SRC && rm */ && echo '2-gcc-pass1' >> $SRC/tmp.log && sync && tar -xf linux-2.6.24.2.tar.bz2 && cd linux-2.6.24.2 && make distclean && make headers_check ARCH=x86 && make headers_install ARCH=x86 INSTALL_HDR_PATH=temp && cp -r temp/include/* /www/include/ && cd $SRC && rm */ && echo '3-kernel-headers' >> $SRC/tmp.log && sync && tar -xf glibc-2.6.1.tar.bz2 && mkdir glibc-build && cd glibc-build && find ../glibc-2.6.1 -name configure | xargs touch && LDFLAGS="`echo $LDFLAGS | sed 's/,--hash-style=gnu//'`" \ ../glibc-2.6.1/configure --prefix=/www --enable-add-ons=nptl --enable-shared --enable-kernel=2.6.22 --disable-oldest-abi --disable-profile --with-headers=/www/include --with-binutils=/www/bin --without-cvs --with-elf --without-gd --without-gmp --without-selinux --with-tls && echo 'MAKEINFO = :' >> configparms && make && ( make -k check 2> $SRC/tmp_glibc.log ; make install ) && cp --remove-destination /www/share/zoneinfo/UTC /www/etc/localtime && cd $SRC && rm */ && echo '4-glibc' >> $SRC/tmp.log && sync && mv /www/bin/{ld-new,ld} && gcc -dumpspecs | sed 's@/lib/ld-linux.so.2@/www/lib/ld-linux.so.2@g' > `dirname $(gcc -print-libgcc-file-name)`/specs && echo 'main(){}' > dummy.c && cc dummy.c && readelf -l a.out | fgrep '[Requesting program interpreter: /www/lib/ld-linux.so.2]' && rm dummy.c a.out && echo '5-Adjusting' >> $SRC/tmp.log && sync && tar -xf tcl8.4.18-src.tar.gz && cd tcl8.4.18/unix && ./configure --prefix=/www --enable-threads --enable-shared --enable-load --enable-gcc --disable-symbols --disable-64bit --disable-64bit-vis --disable-langinfo --disable-corefoundation --disable-dtrace --disable-framework --disable-man-symlinks --disable-man-compression --disable-man-suffix && make && make install install-private-headers && ln -sf tclsh8.4 /www/bin/tclsh && cd $SRC && rm */ && sync && tar -xf expect-5.43.0.tar.bz2 && cd expect-5.43 && patch $SRC/expect-5.43.0-spawn-2.patch && sed -i 's/STTY_BIN=.*/STTY_BIN=stty/g' configure{.in,} && ./configure --prefix=/www --enable-threads --enable-shared --enable-load --enable-gcc --with-tcl=/www/lib --with-tclinclude=/www/include --with-x=no --disable-symbols && make expect && make install SCRIPTS="" && cd $SRC && rm */ && sync && tar -xf dejagnu-1.4.4.tar.gz && cd dejagnu-1.4.4 && ./configure --prefix=/www && make install && cd $SRC && rm */ && echo '6-tcl-expect-dejagnu' >> $SRC/tmp.log && sync && tar -xf gcc-core-4.2.3.tar.bz2 && tar -xf gcc-testsuite-4.2.3.tar.bz2 && cd gcc-4.2.3 && sed -r -i 's|^LDFLAGS(_FOR_TARGET)? =|& @LDFLAGS@|' Makefile.in && sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in && sed -i -e's@\./fixinc\.sh@-c true@' -e'/^LIBGCC2_DEBUG_CFLAGS/d' gcc/Makefile.in && sed -i '/MULTILIB_OSDIRNAMES/d' gcc/config/i386/t-linux64 && echo '/* Remove /usr/include from end of include search path. */ #undef STANDARD_INCLUDE_DIR #define STANDARD_INCLUDE_DIR 0' | tee -a gcc/config/linux.h gcc/config/i386/linux{,64}.h && sed -i 's@/lib/ld.so@/www&@g' gcc/config/i386/gnu.h && sed -i 's@/lib/ld-linux.so.2@/www&@g' gcc/config/i386/linux{,64}.h && sed -i 's@/lib64/ld-linux-x86-64.so.2@/www&@g' gcc/config/i386/linux64.h && # sed -i '/LINK_SPEC/s/ "/&--hash-style=gnu /' gcc/config/i386/linux{,64}.h && mkdir ../gcc-build && cd ../gcc-build && ../gcc-4.2.3/configure --prefix=/www --with-local-prefix=/www --enable-languages=c --enable-bootstrap --disable-nls --disable-rpath --disable-multilib --enable-shared=libgcc --enable-static=libgcc --disable-libgomp --disable-libmudflap --disable-libssp --enable-linux-futex --enable-threads=posix --enable-tls --disable-symvers --with-as=/www/bin/as --with-ld=/www/bin/ld --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --without-gmp --without-mpfr --without-system-libunwind --without-system-zlib --with-pic --without-x && make profiledbootstrap LIBCFLAGS="$CFLAGS" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" && ( make -k check | tee $SRC/tmp_gcc.log ; make install ) && INC=`gcc -print-file-name=include` && TOL=`gcc -print-file-name=install-tools` && rm $INC/* && cp $TOL/include/* $INC && cp $TOL/gsyslimits.h $INC/syslimits.h && unset INC TOL && cd $SRC && rm */ && sync && echo 'main(){}' > dummy.c && cc dummy.c && readelf -l a.out | fgrep '[Requesting program interpreter: /www/lib/ld-linux.so.2]' && rm dummy.c a.out && echo '7-gcc-pass2' >> $SRC/tmp.log && sync && tar -xf binutils-2.18.tar.bz2 && mkdir binutils-build && cd binutils-build && echo 'MAKEINFO = :' >> ../binutils-2.18/Makefile.in && CFLAGS="$CFLAGS -fno-inline-functions" \ ../binutils-2.18/configure --prefix=/www --with-lib-path=/www/lib --disable-nls --disable-rpath --disable-multilib --disable-shared --enable-static --disable-werror --without-gmp --without-mpfr --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --with-pic && make all check install tooldir=/www/ && make clean-ld all-ld check-ld LIB_PATH=/lib:/usr/lib tooldir=/www/ && cp ld/ld-new /www/bin/ && cp ../binutils-2.18/include/libiberty.h /www/include/ && cd $SRC && rm */ && echo '8-binutils-pass2' >> $SRC/tmp.log && sync && tar -xf bash-3.2.tar.gz && cd bash-3.2 && patch $SRC/bash-3.2-fixes-7.patch && ./configure --prefix=/www --disable-minimal-config --disable-profiling --enable-static-link --disable-nls --disable-rpath --without-lispdir --without-afs --without-bash-malloc --without-gnu-malloc --without-curses --without-termcap --disable-install-termcap --with-installed-readline=no --without-purecov --without-purify --without-libiconv-prefix --without-included-gettext --without-libintl-prefix && make && cp bash /www/bin/ && ln -sf bash /www/bin/sh && cd $SRC && rm */ && echo '9-bash' >> $SRC/tmp.log && sync && tar -xf bzip2-1.0.4.tar.gz && cd bzip2-1.0.4 && make bzip2 CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64" LDFLAGS="$LDFLAGS" && cp bzip2 /www/bin/ && ln -sf bzip2 /www/bin/bunzip2 && cd $SRC && rm */ && echo '10-bzip2' >> $SRC/tmp.log && sync && tar -xf coreutils-6.10.tar.gz && cd coreutils-6.10 && sed -i '/(setuid_root_mode)/s/(installed_su)/&;/' src/Makefile.in && ./configure --prefix=/www --enable-option-checking --disable-acl --disable-assert --disable-rpath --disable-nls --enable-install-program="arch,hostname,su" --without-libiconv-prefix --without-included-regex --without-libintl-prefix && make && make install install-root && cd $SRC && rm */ && echo '11-coreutils' >> $SRC/tmp.log && sync && tar -xf diffutils-2.8.1.tar.gz && cd diffutils-2.8.1 && ./configure --prefix=/www --disable-rpath --disable-nls --without-libiconv-prefix --without-included-regex --without-libintl-prefix && make && cp src/{cmp,diff} /www/bin/ && cd $SRC && rm */ && echo '12-diffutils' >> $SRC/tmp.log && sync && tar -xf findutils-4.2.33.tar.gz && cd findutils-4.2.33 && ./configure --prefix=/www --disable-id-cache --disable-debug --disable-leaf-optimisation --disable-d_type-optimization --disable-nls --disable-rpath --without-included-regex --without-libiconv-prefix --without-libintl-prefix && make && cp find/find xargs/xargs /www/bin/ && cd $SRC && rm */ && echo '13-findutils' >> $SRC/tmp.log && sync && tar -xf gawk-3.1.6.tar.bz2 && cd gawk-3.1.6 && ./configure --prefix=/www --disable-portals --enable-lint --enable-switch --enable-directories-fatal --disable-nls --disable-rpath --without-whiny-user-strftime --without-libiconv-prefix --without-libintl-prefix && make && cp gawk /www/bin/ && ln -sf gawk /www/bin/awk && cd $SRC && rm */ && echo '14-gawk' >> $SRC/tmp.log && sync && tar -xf grep-2.5.3.tar.bz2 && cd grep-2.5.3 && sed -i '/^SUBDIRS/s/doc//' Makefile.in && ./configure --prefix=/www --disable-perl-regexp --disable-nls --without-libiconv-prefix --without-included-gettext --without-included-regex --without-included-getopt && make && cp src/{,e,f}grep /www/bin/ && cd $SRC && rm */ && echo '15-grep' >> $SRC/tmp.log && sync && tar -xf gzip-1.3.12.tar.gz && cd gzip-1.3.12 && sed -i 's/futimens/gl_&/' gzip.c lib/utimens.{c,h} && ./configure --prefix=/www && make && cp gunzip gzip /www/bin/ && cd $SRC && rm */ && echo '16-gzip' >> $SRC/tmp.log && sync && tar -xf make-3.81.tar.bz2 && cd make-3.81 && ./configure --prefix=/www --disable-nls --disable-rpath --enable-job-server --without-libiconv-prefix --without-libintl-prefix --without-customs --without-dmalloc && make && cp make /www/bin/ && cd $SRC && rm */ && echo '17-make' >> $SRC/tmp.log && sync && tar -xf patch-2.5.4.tar.gz && cd patch-2.5.4 && ./configure --prefix=/www && make && cp patch /www/bin/ && cd $SRC && rm */ && echo '18-patch' >> $SRC/tmp.log && sync && tar -xf perl-5.8.8.tar.bz2 && cd perl-5.8.8 && sed -i -e's:/lib/libc.so.6:/www&:g' -e's:libc=/lib/$libc:libc=/www/lib/$libc:g' hints/linux.sh && echo 'locincpth="" ; loclibpth="" ; usrinc="/www/include" ; glibpth="/www/lib"' >> hints/linux.sh && sed -i 's/command /command[ -]/' makedepend.SH && ./configure.gnu --prefix=/www -Dstatic_ext='Data/Dumper Fcntl IO POSIX' && make && make install.perl && cd $SRC && rm */ && echo '19-perl' >> $SRC/tmp.log && sync && tar -xf sed-4.1.5.tar.gz && cd sed-4.1.5 && ./configure --prefix=/www --enable-i18n --enable-regex-tests --disable-html --disable-nls --without-included-regex --without-libiconv-prefix --without-included-gettext --without-libintl-prefix && make && cp sed/sed /www/bin/ && cd $SRC && rm */ && echo '20-sed' >> $SRC/tmp.log && sync && tar -xf tar-1.19.tar.bz2 && cd tar-1.19 && ./configure --prefix=/www --disable-rpath --disable-nls --disable-backup-scripts --without-included-regex --without-libiconv-prefix --without-libintl-prefix && make && cp src/tar /www/bin/ && cd $SRC && rm */ && echo '21-tar' >> $SRC/tmp.log && sync && tar -xf util-linux-2.12r.tar.bz2 && cd util-linux-2.12r && sed -i 's:/usr/include:/www/include:g' configure && sed -i 's|CPUOPT=.*|CPUOPT=|' MCONFIG && LDFLAGS="$LDFLAGS -static" ./configure && make -C lib && make -C mount mount umount && cp mount/{,u}mount /www/bin/ && cd $SRC && rm */ && echo '22-util-linux' >> $SRC/tmp.log && sync && tar -xf linux-2.6.24.2.tar.bz2 && cd linux-2.6.24.2 && make distclean && cp $SRC/linux-2.6.24-config.txt .config && chown -R nobody . && su -c'make silentoldconfig ARCH=x86' -s/www/bin/bash - nobody && echo 'cflags-y += -march=athlon-xp' | tee arch/x86/Makefile*.cpu && make ARCH=x86 V=0 CC="gcc -m32 $CFLAGS" LD="ld -m elf_i386 $kLDFLAGS" && cp arch/x86/boot/bzImage $LFS/boot/ && cd $SRC && rm */ && echo '23-linux' >> $SRC/tmp.log && sync && tar -xf iproute2-2.6.24-rc7.tar.bz2 && cd iproute2-2.6.24-rc7 && sed -i -e's|^SBINDIR=.*|SBINDIR=/www/bin|' -e's|^CONFDIR=.*|CONFDIR=/www/etc/iproute2|' -e's|^SUBDIRS=.*|SUBDIRS=lib ip|' -e's|$(KERNEL_INCLUDE)|/www/include|' Makefile && make CCOPTS="-D_GNU_SOURCE $CFLAGS" LDFLAGS="$LDFLAGS" && cp ip/ip /www/bin/ && cp -R etc/iproute2/ /www/etc/ && cd $SRC && rm */ && echo '24-iproute2' >> $SRC/tmp.log && sync && [ "`ldd /www/{bin,sbin}/* /www/lib/*{,/*{,/*{,/*{,/*}}}} | egrep ' => /(usr|lib)'`" = '' ] && rm /www/{sbin,info,man} /www/share/{info,man,zoneinfo} && ( strip --strip-debug /www/lib/*{,/*{,/*{,/*{,/*}}}} ; strip --strip-all /www/bin/* ; sync ) && echo 'tool-chain-finished!' >> $SRC/tmp.log && sync &&
到此,工具链制作完毕,可以通过查看 $SRC/tmp*.log 来了解制作过程是否顺利。如果没有很严重的错误,那么就可以准备下面的重启了。
  csfrank 当前离线   回复时引用此帖
旧 08-03-03, 10:11 第 5 帖
csfrank 帅哥
 
csfrank 的头像
 
 
注册会员  
  注册日期: Jun 2005
  我的住址: 上海
  帖子: 501
  精华: 20
 

重启工具链
与 LFS 的标准做法不同,本文为了尽可能摆脱宿主系统的影响,做完工具链之后不是chroot进入虚根环境,而是做一些必要的准备工作,然后重新启动计算机,进入一个完全与宿主系统无关的工具链环境,再继续完成目标系统的构建。

创建基础目录结构、必需的符号连接与文件、存储随机数种子、用户和组([注意]pgsql属于www组,root的密码是"123"):
[提示]如果现在就将 mtab 指向 /proc/mounts 的话,Coreutils 测试程序会将 /dev/root 挂载到 tests/rm/one-file-system.tmp/ 下的某个目录中,从而导致无法删除Coreutils 的编译目录。
代码:
mkdir $LFS/{boot,bin,etc,lib,dev/{pts,shm},share,root,usr/{bin,lib},var/log,www,data,proc} && ln -sf /dev/shm/tmp $LFS/tmp && ln -sf /dev/shm/run $LFS/var/run && touch $LFS/etc/mtab $LFS/var/log/{btmp,lastlog,wtmp} && ln -sf bash $LFS/bin/sh && cp /www/bin/{bash,echo,mount} $LFS/bin/ && ln -sf /www/bin/{env,perl} $LFS/usr/bin/ && ln -sf /www/lib/libgcc_s.so.1 $LFS/usr/lib/ && dd if=/dev/urandom of=$LFS/var/random-seed bs=8k count=1 && dd if=/dev/urandom of=$LFS/var/urandom-seed bs=8k count=1 && echo 'root:$1$/y21SFaU$uQ0nsncCJcYjrfgJ9qvA31:0:0:SuperUser:/root:/bin/bash httpd:*:1001:1000:httpdDaemon:/www:/bin/false pgsql:*:1002:1000:pgsqlDaemon:/data:/bin/false sshd:*:3001:3000:sshdPrivSep:/share/empty:/bin/false' > $LFS/etc/passwd && echo 'root::0: www::1000: sshd::3000:' > $LFS/etc/group &&
Linux 中的设备有2种类型:字符设备(无缓冲且只能顺序存取)、块设备(有缓冲且可以随机存取)。每个字符设备和块设备都必须有主、次设备号,主设备号相同的设备是同类设备(使用同一个驱动程序)。这些设备中,有些设备是对实际存在的物理硬件的抽象,而有些设备则是内核自身提供的功能(不依赖于特定的物理硬件,又称为"虚拟设备")。每个设备在 /dev 目录下都有一个对应的文件(节点)。可以通过 cat /proc/devices 命令查看当前已经加载的设备驱动程序的主设备号。内核能够识别的所有设备都记录在原码树下的 Documentation/devices.txt 文件中。在 /dev 目录下除了字符设备和块设备节点之外还通常还会存在:FIFO管道、Socket、软/硬连接、目录。这些东西没有主/次设备号。欲了解更多有关 Linux设备文件的知识,可以参考本文作者的一篇文章:《Linux设备文件简介》
由于本文不打算使用 Udev ,因此这里手动创建所有设备。
代码:
# mkfifo -m 600 $LFS/dev/initctl && mknod -m 666 $LFS/dev/null c 1 3 && mknod -m 666 $LFS/dev/zero c 1 5 && mknod -m 666 $LFS/dev/full c 1 7 && mknod -m 666 $LFS/dev/random c 1 8 && mknod -m 666 $LFS/dev/urandom c 1 9 && mknod -m 666 $LFS/dev/tty0 c 4 0 && mknod -m 666 $LFS/dev/tty1 c 4 1 && mknod -m 666 $LFS/dev/tty2 c 4 2 && mknod -m 666 $LFS/dev/tty3 c 4 3 && mknod -m 666 $LFS/dev/tty c 5 0 && mknod -m 666 $LFS/dev/console c 5 1 && mknod -m 666 $LFS/dev/ptmx c 5 2 && mknod -m 666 $LFS/dev/sda b 8 0 && mknod -m 666 $LFS/dev/sda1 b 8 1 && mknod -m 666 $LFS/dev/sda2 b 8 2 && mknod -m 666 $LFS/dev/sda3 b 8 3 && mknod -m 666 $LFS/dev/sda4 b 8 4 && mknod -m 666 $LFS/dev/sda5 b 8 5 && mknod -m 666 $LFS/dev/sda6 b 8 6 && mknod -m 666 $LFS/dev/sda7 b 8 7 && mknod -m 666 $LFS/dev/sda8 b 8 8 && mknod -m 666 $LFS/dev/sda9 b 8 9 && mknod -m 666 $LFS/dev/rtc c 10 135 && mknod -m 666 $LFS/dev/hpet c 10 228 && ln -sf /proc/self/fd $LFS/dev/fd && ln -sf /proc/self/fd/0 $LFS/dev/stdin && ln -sf /proc/self/fd/1 $LFS/dev/stdout && ln -sf /proc/self/fd/2 $LFS/dev/stderr && ln -sf /proc/kcore $LFS/dev/core &&
由于安装 Iana-Etc 包之后将会产生巨大的 /etc/services 文件,从而对性能有不良影响(比如 getservbyname() 函数将会变慢),因此本文并未安装 Iana-Etc 包。但是 Prel 的 ext/IO/ 与 lib/Net/ 目录下的几个测试套件依赖于 Iana-Etc 包。因此为了测试的完整性,先从宿主系统复制临时的 /etc/{protocols,services} 文件,然后在 Perl 测试完毕之后再删除它们。此外,好几个 Perl 测试项目都需要 /etc/hosts 文件来解析 localhost 的名称("miniLAPP"),为了顺利运行测试套件,这里也提前创建它:
代码:
cp /etc/{protocols,services} $LFS/etc/ && echo '127.0.0.1 localhost miniLAPP' > $LFS/etc/hosts &&
设置Bash启动脚本,一方面是为了做编译前的准备,另一方面也是为了简化了关机后的状态回复工作。[提示]"umask 000"会导致 Coreutils 测试失败。TERM环境变量将由系统自动设置。
代码:
echo "set +h umask 022 export HOME=/root PS1='$PS1' TZ=$TZ SRC=/data export PATH=/bin:/usr/bin:/www/bin export CFLAGS='$CFLAGS' LDFLAGS='$LDFLAGS' kLDFLAGS='$kLDFLAGS' alias make='make -j1' mkdir='mkdir -p' patch='patch -p1 -i' mv='mv -f' cp='cp -pf' rm='rm -fr' echo miniLAPP > /proc/sys/kernel/hostname mkdir -m 1777 /dev/shm/{tmp,run,pg_socket,php_session} touch /var/run/utmp cd \$SRC" > $LFS/etc/profile &&
编写启动脚本。
代码:
echo '#!/bin/bash /bin/mount -t proc proc /proc && /bin/mount -t tmpfs shm /dev/shm && /bin/mount -t devpts devpts /dev/pts && /bin/mount -t ext2 /dev/sda1 /boot && /bin/mount -t xfs /dev/sda5 /usr && /bin/mount -t xfs /dev/sda6 /root && /bin/mount -t xfs /dev/sda7 /var && /bin/mount -t xfs /dev/sda8 /www && /bin/mount -t xfs /dev/sda9 /data && /www/bin/ip -4 link set lo txqueuelen 0 && /www/bin/ip -4 link set eth0 txqueuelen 4000 && /www/bin/ip -4 link set lo mtu 16436 && /www/bin/ip -4 link set eth0 mtu 1500 && /www/bin/ip -4 addr add 127.0.0.1/8 scope host dev lo valid_lft forever preferred_lft forever && /www/bin/ip -4 addr add 192.168.10.33/24 broadcast 192.168.10.255 scope global dev eth0 valid_lft forever preferred_lft forever && /www/bin/ip -4 link set lo up && /www/bin/ip -4 link set eth0 up && /www/bin/ip -4 route add unicast default via 192.168.10.250 dev eth0 && /bin/bash --login +h' > $LFS/bin/tmpinit && chmod 755 $LFS/bin/tmpinit &&
由于GRUB-0.97年久失修,毛病多多,因此这里使用咱们中国人主导开发的GRUB4DOS
代码:
cp $SRC/grldr $LFS/boot/ && echo 'kernel (hd0,0)/bzImage root=0802 rootfstype=xfs rw init=/bin/tmpinit panic=30' > $LFS/boot/menu.lst && chmod +x $SRC/bootlace.com && $SRC/bootlace.com --no-backup-mbr --mbr-disable-floppy --mbr-disable-osbr --boot-prevmbr-last /dev/sda &&
接下来有两个分支可选,推荐使用默认的分支㈠,因为分支㈡未经本文作者严格测试,可能会存在某些问题。
分支㈠[关机]
关机前的准备(如果没有启动ssh就省略相应的命令):
代码:
/etc/rc.d/init.d/sshd stop && rm ~/.bash* && sync && exit
必须确保一直 exit 到出现"Press Enter to activate this virtual console..."为止,然后再按回车键重新登陆并按下列步骤关机:
代码:
cd / && rm -f /etc/mtab && umount /dev/sda{9,8,7,6,5,1,2} && poweroff
OK! 下次重新开机的时候将BIOS中的启动盘调整为硬盘,即可继续进行下面"编译最终系统"的工作。

分支㈡[chroot]
为了方便期望在编译最终系统的过程中也能使用ssh的读者,这里也介绍一下传统的chroot方法。需要说明的是,由于此分支的方法不能完全摆脱宿主系统的影响,所以本文不推荐使用。仅供那些贪图copy/paste便利的玩家参考和测试。
代码:
mount -t devpts devpts $LFS/dev/pts && mount -t tmpfs shm $LFS/dev/shm && mount -t proc proc $LFS/proc && chroot $LFS /usr/bin/env -i TERM=$TERM /bin/bash --login +h
  csfrank 当前离线   回复时引用此帖
旧 08-03-03, 10:13 第 6 帖
csfrank 帅哥
 
csfrank 的头像
 
 
注册会员  
  注册日期: Jun 2005
  我的住址: 上海
  帖子: 501
  精华: 20
 

依赖关系分析
在正式开始编译最终系统之前,我们需要静下心来认真分析一下这个最终系统究竟需要哪些东西。

所谓"依赖性"是多方面的。一般来说,可以分为"运行时依赖"、"编译安装依赖"、"测试依赖"三个层面。为了构建一个严谨的自依赖系统,显然这三种依赖性都必须满足。运行时依赖比较简单,一般就是库的依赖;而后两种依赖则比较复杂(运行时依赖实际上取决于编译安装依赖)。比如,如果你不需要安装文档,那么 Textinfo 就不是必须的;如果你不需要国际化支持,那么 GetText 也不是必需的,等等。庆幸的是 LFS-Book 的附录部分给出了宝贵的依赖关系资料,可以提供参考,这样可以省去很多麻烦。

首先,我们来看看"核心"部分需要哪些东西。很显然,下面这些是必须的:GRUB, Kernel, Glibc, Sysklogd, Dcron, Bash, IPRoute2, Apache, PHP, PostgreSQL, OpenSSH, Iptables 。再深入思考一下,就会发现如下组件也是"核心"部分必须的:E2fsprogs(被mount和xfs_repair依赖),XFS(用于开机时的磁盘检查),Ncurses(被Readline/Bash依赖),Readline(被Bash/PostgreSQL依赖),Zlib(被 Apache/PostgreSQL/OpenSSH依赖),JPEG+PNG(被PHP依赖),PCRE(被Apache/PHP依赖), OpenSSL(被Apache/OpenSSH/PostgreSQL依赖),Util-linux 与 Coreutils 中的部分程序。核心部分只需要满足运行时依赖即可。

然后,再看看"扩展"部分需要哪些东西。这部分的选择因人而异,这里就大致选择了几个系统管理相关的组件和几个实用工具:Coreutils, Procps, Psmisc, Util-linux, Bzip2, Findutils, Grep, Sed, Tar, XFS 。选择这部分组件时,暂时无需考虑依赖关系。

最后,考虑到可扩展性以及将来的组件升级与维护等,就必须构建一个自依赖的系统。也就是说,所有组件加在一起必须能构成一个完整的依赖环(3种依赖关系全部满足)。本文安装的、并且未在前面提到的软件包都属于这个用途。它们都属于"扩展"。

需要说明的是,这里的"核心"与"扩展"的划分不是绝对严格的:扩展部分的组件严格属于"扩展",而核心部分的组件通常只有某一部分属于"核心" (其他部分归入"扩展")。比如 Glibc 的基本库部分就属于"核心",而扩展库、实用程序、文档、头文件等则属于"扩展"。
包管理
其实这么简单的系统根本不需要包管理,所以本文并不使用任何一种包管理技术,只是使用了一种非常简单的 DESTDIR 方法来将每个包都复制一份到/root目录下,以方便管理员查看每个软件包究竟安装了哪些东西。当然,并不是所有软件包都遵循这个约定俗成的规则,对于这些软件包使用的命令也有所不同。

编译最终系统
配置选项
要做到最大限度的定制每一个软件包,获取完整的配置选项是必须的。当然,要想更加详细、全面的了解如何自定义安装,还需要查看 README INSTALL FAQ 之类的文档,甚至是软件包的官方手册。需要注意的是,有不少软件包的配置选项分布在多个 configure 脚本中,还有少数并不是通过 configure 脚本进行配置的,查看完整的配置信息就变成一件很吃力的事情了。因此唯一的建议就是:读文档、读文档、再读文档。当然,鸟语是免不了的...

关机与状态回复
由于编译过程漫长,下面的编译步骤被设计为"易于恢复状态的"(仅对"分支㈠"有效),意思是,你可以在编译完任意一个软件包之后关机,并且重新开机后就已经自动的恢复了工作状态。要达到这个目的,你可以使用任何你喜欢的方式关机(比如直接拔掉电源),但是你必须确保在关机前运行了"sync"命令。

对于分支㈡,恢复步骤如下:
①使用 LiveCD 开机,直接按回车键启动,所有设置均采用默认。
②如果希望使用ssh进行远程安装,步骤同前。
③挂载文件系统后进入虚根环境,即可完成状态恢复:
代码:
export LFS=/mnt/lfs && mkdir -p $LFS && mount -t xfs /dev/sda2 $LFS && mount -t ext2 /dev/sda1 $LFS/boot && mount -t xfs /dev/sda5 $LFS/usr && mount -t xfs /dev/sda6 $LFS/root && mount -t xfs /dev/sda7 $LFS/var && mount -t xfs /dev/sda8 $LFS/www && mount -t xfs /dev/sda9 $LFS/data && mount -t devpts devpts $LFS/dev/pts && mount -t tmpfs shm $LFS/dev/shm && mount -t proc proc $LFS/proc && chroot $LFS /usr/bin/env -i TERM=$TERM /bin/bash --login +h
[提示]如果你和我一样使用虚拟机的暂停功能,那么重新连接ssh后只要使用最后一句chroot命令即可。甚至可以在chroot前用下面的命令偷懒到底:
代码:
echo "chroot $LFS /usr/bin/env -i TERM=\$TERM /bin/bash --login +h" > /etc/profile

此帖于 08-03-03 10:15 被 csfrank 编辑.
  csfrank 当前离线   回复时引用此帖
旧 08-03-03, 10:24 第 7 帖
csfrank 帅哥
 
csfrank 的头像
 
 
注册会员  
  注册日期: Jun 2005
  我的住址: 上海
  帖子: 501
  精华: 20
 

内核头文件
根据 Glibc 的 FAQ ,编译 Glibc 时使用的内核头文件版本可以比实际运行 Glibc 的内核版本高。比如用于编译 Glibc 的内核头文件版本为 2.6.24 ,但是实际运行 Glibc 的可以是 2.6.16 版本的内核(编译 Glibc 时必须使用 --enable-kernel=2.6.16 而不能使用 --enable-kernel=2.6.24 )。允许这样做的好处是即使将来把内核升级到 2.6.24 也不需要重新编译 Glibc 了。另一方面,如果实际运行的内核版本比头文件版本高,那么新内核的新特性(主要是系统调用)将无法被Glibc使用。[注意]不要直接 INSTALL_HDR_PATH=/usr ,这样可能使得Glibc变得不稳定。[小提示]如果将来把内核升级为更高版本,头文件是不是也需要跟着一起升级?答案是:NO!! 关于内核头文件变迁的历史,这里有一篇《[八卦故事]内核头文件传奇》,可以当作课外读物
代码:
( test ! -f $SRC/build.log ) && [ "`pwd`" = "$SRC" ] && R=/root/linux-headers-2.6.24.2/ && tar -xf linux-2.6.24.2.tar.bz2 && cd linux-2.6.24.2 && make distclean && make headers_check ARCH=x86 && make headers_install ARCH=x86 INSTALL_HDR_PATH=$R/usr && cp -r $R/usr/include /usr/ && cd $SRC && rm */ && echo '1-kernel-headers' >> $SRC/build.log && sync &&
Glibc
Glibc 的安装指南中说测试套件中的某些测试项目是假定以非 root 身份运行的,因此建议使用普通用户身份进行编译与安装。不过经过实践,以 root 用户进行编译和安装也没问题。这里仅安装了 zh_CN.UTF-8 的 locale 支持,如果你想支持更多的 locale 请自己添加适当的 localedef 命令。出于安全最大化的考虑还禁用了 DNS 。将时区设为UTC(相当于取消时区的概念,如果你有使用时区的需求可以设为"PRC")。更多关于安装 Glibc 的信息,请查看源码树下的 configure INSTALL FAQ 三个文件。[提示]由于没有安装C++编译器的缘故,bug-atexit3-lib.os tst-cancel24.o c++-types-check 测试将会失败,你可以安全的忽略它。touch用于阻止可能发生的Autoconf调用(当Makefile检测到一个configure文件的时间戳比它对应的configure.in文件旧的时候),这种调用有时候会导致编译失败。将"/dev/log"修改为"/dev/shm/log"是因为将来的根文件系统是只读挂载的,而syslogd会在启动的时候删除并重建此socket。Glibc GCC Binutils 三者是整个工具链的核心,因此如何对其进行定制就显得很重要。这里有一篇文章《Glibc 安装指南》,可以在漫长的编译过程中作为参考资料读一读。
代码:
R=/root/glibc-2.6.1/ && mkdir {,$R}/usr/lib/locale && tar -xf glibc-2.6.1.tar.bz2 && cd glibc-2.6.1 && sed -i 's|libs -o|libs -L/usr/lib -Wl,-dynamic-linker=/lib/ld-linux.so.2 -o|' scripts/test-installation.pl && sed -r -i 's:/bin/(pwd|cat):\1:g' configure{.in,} io/ftwtest-sh stdio-common/{test-popen,xbug,tstscanf}.c && sed -i -e's|^rootsbindir =.*|rootsbindir=/usr/bin|' -e's|^sbindir =.*|sbindir=/usr/bin|' Makeconfig && sed -i 's|^sbindir=.*|sbindir=/usr/bin|' {,posix/glob/}configure && sed -i 's|libc_cv_rootsbindir=.*|libc_cv_rootsbindir=/usr/bin|' sysdeps/unix/sysv/linux/configure && sed -i 's|/dev/log|/dev/shm/log|' bits/syslog-path.h && find . -name configure | xargs touch && mkdir ../glibc-build && cd ../glibc-build && ../glibc-2.6.1/configure --prefix=/usr --sbindir=/usr/bin --enable-add-ons=nptl --enable-shared --enable-kernel=2.6.22 --disable-oldest-abi --enable-omitfp --disable-profile --with-headers=/usr/include --with-binutils=/www/bin --without-cvs --with-elf --without-gd --without-gmp --without-selinux --with-tls && echo 'MAKEINFO = :' >> configparms && make && ( make -k check 2> $SRC/build_glibc.log ; make install ) && make install install_root=$R && localedef -i zh_CN -f UTF-8 zh_CN.UTF-8 && cp /usr/lib/locale/* $R/usr/lib/locale/ && rm {,$R}/etc/rpc {,$R}/{,usr}/lib/*_g.* {,$R}/usr/libexec/pt_chown {,$R}/usr/share/locale && echo 'passwd: files group: files shadow: files hosts: files networks: files protocols: files services: files ethers: files rpc: files' | tee {,$R}/etc/nsswitch.conf && cp --remove-destination /usr/share/zoneinfo/UTC /etc/localtime && cp --remove-destination /usr/share/zoneinfo/UTC $R/etc/localtime && cp /etc/{passwd,group,hosts} $R/etc/ && cd $SRC && rm */ && echo '2-glibc' >> $SRC/build.log && sync &&
再次调整工具链
代码:
mv /www/bin/{ld-new,ld} && gcc -dumpspecs | sed -e'/^\*link:$/{n;s@$@ -L/usr/lib@}' -e's@/www/lib/ld-linux.so.2@/lib/ld-linux.so.2@g' -e'/^\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' -e'/^\*cpp:$/{n;s@$@ -isystem /usr/include@}' > `dirname $(gcc -print-libgcc-file-name)`/specs && echo 'main(){}' > dummy.c && cc dummy.c -v -Wl,--verbose &> dummy.log && readelf -l a.out | fgrep '[Requesting program interpreter: /lib/ld-linux.so.2]' && fgrep 'attempt to open /usr/lib/crt1.o succeeded' dummy.log && fgrep 'attempt to open /usr/lib/crti.o succeeded' dummy.log && fgrep 'attempt to open /usr/lib/crtn.o succeeded' dummy.log && fgrep '#include <...> search starts here: /usr/include /www/include' dummy.log && # fgrep 'SEARCH_DIR("/www/i686-pc-linux-gnu/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");' dummy.log && fgrep 'attempt to open /lib/libc.so.6 succeeded' dummy.log && fgrep 'found ld-linux.so.2 at /lib/ld-linux.so.2' dummy.log && rm dummy.c a.out dummy.log && echo '3-adjusting' >> $SRC/build.log && sync &&
Tcl + Expect + DejaGNU
[提示]使用 --with(out)-tk 将导致 expect 配置失败,使用了 --with-tcl 之后就不需要再详细指定 --with-tclconfig --with-tcllib --with-tcllibdir 了。使用 --with(out)-docbook 或 --with(out)-oskith 将导致 dejagnu 配置失败。sed 一定要先修改 configure.in 再修改 configure ,否则会导致 Autoconf 的调用。dejagnu 的安装指南说测试套件需要以非 root 身份运行,可是经过实践,无论 root 与否,都不能在第一次安装后立即通过测试,一般需要安装两次甚至三次才能测试成功(无论是否root都是这样),不知何故。再加上dejagnu的测试程序依赖于这里并不存在的C++编译器,因此这里跳过dejagnu测试。
代码:
R=/root/tcl8.4.18/ && tar -xf tcl8.4.18-src.tar.gz && cd tcl8.4.18/unix && sed -i 's:/bin/rm:rm:g' ../library/ldAout.tcl && ./configure --prefix=/usr --sbindir=/usr/bin --enable-threads --enable-shared --enable-load --enable-gcc --disable-symbols --disable-64bit --disable-64bit-vis --disable-langinfo --disable-corefoundation --disable-dtrace --disable-framework --disable-man-symlinks --disable-man-compression --disable-man-suffix && make && TZ=UTC make test && make install install-private-headers && ln -sf tclsh8.4 /usr/bin/tclsh && make install install-private-headers INSTALL_ROOT=$R && ln -sf tclsh8.4 $R/usr/bin/tclsh && cd $SRC && rm */ && sync && tar -xf expect-5.43.0.tar.bz2 && cd expect-5.43 && patch $SRC/expect-5.43.0-spawn-2.patch && sed -i 's/STTY_BIN=.*/STTY_BIN=stty/g' configure{.in,} && ./configure --prefix=/usr --sbindir=/usr/bin --enable-threads --enable-shared --enable-load --enable-gcc --with-tcl=/usr/lib --with-tclinclude=/usr/include --with-x=no --disable-symbols && make expect && make test && make install SCRIPTS="" && make install SCRIPTS="" INSTALL_ROOT=/root/expect-5.43.0/ && cd $SRC && rm */ && sync && tar -xf dejagnu-1.4.4.tar.gz && cd dejagnu-1.4.4 && ./configure --prefix=/usr --sbindir=/usr/bin && make install && make install DESTDIR=/root/dejagnu-1.4.4/ && cd $SRC && rm */ && echo '4-tcl-expect-dejagnu' >> $SRC/build.log && sync &&
Binutils
由于"-finline-functions"会导致ld测试出现多处错误,因此这里需要专门禁用它。对Makefile.in的修改用于移除对 makeinfo的依赖,否则编译将会失败(因为工具链中并未安装Texinfo)。[提示]由于 binutils-2.17 的测试套件将路径 /bin/stty 进行了硬编码,且本文作者尚未找到简便的迂回方法,因此如果你使用的是 2.17 ,那么要先建立一个符号链接来满足测试套件的需求,安装完毕后再删除它。对于如何安装 Binutils 和 GCC 可以参考一下《Binutils与GCC配置选项简介》
代码:
R=/root/binutils-2.18/ && tar -xf binutils-2.18.tar.bz2 && mkdir binutils-build && cd binutils-build && echo 'MAKEINFO = :' >> ../binutils-2.18/Makefile.in && CFLAGS="$CFLAGS -fno-inline-functions" \ ../binutils-2.18/configure --prefix=/usr --sbindir=/usr/bin --with-lib-path=/lib:/usr/lib --disable-nls --disable-rpath --disable-multilib --enable-shared --disable-static --disable-werror --without-gmp --without-mpfr --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --with-pic && make all check install tooldir=/usr/ && cp ../binutils-2.18/include/libiberty.h /usr/include/ && make install tooldir=/usr/ DESTDIR=$R && cp ../binutils-2.18/include/libiberty.h $R/usr/include/ && cd $SRC && rm */ && echo '5-binutils' >> $SRC/build.log && sync &&
GCC
因为GCC的Makefile.in并不传递LDFLAGS,所以需要sed一下。为了得到更加高效的编译器,这里使用"make profiledbootstrap"代替"make"。对"LINK_SPEC"的修改是为了将"--hash-style=gnu"选项添加到默认的连接器选项中去,如果你希望这样的话,就去掉相应的注释。[提示]如果Glibc的CFLAGS中使用了-freg-struct-return的话, gcc.dg/struct-ret-libc.c测试将会失败,不过这是二进制兼容性所致,可以安全的忽略它。
代码:
R=/root/gcc-4.2.3/ && tar -xf gcc-core-4.2.3.tar.bz2 && tar -xf gcc-testsuite-4.2.3.tar.bz2 && cd gcc-4.2.3 && sed -r -i 's|^LDFLAGS(_FOR_TARGET)? =|& @LDFLAGS@|' Makefile.in && sed -i -e's@\./fixinc\.sh@-c true@' -e'/^LIBGCC2_DEBUG_CFLAGS/d' gcc/Makefile.in && sed -i '/MULTILIB_OSDIRNAMES/d' gcc/config/i386/t-linux64 && sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in && # sed -i '/LINK_SPEC/s/ "/&--hash-style=gnu /' gcc/config/i386/linux{,64}.h && mkdir ../gcc-build && cd ../gcc-build && ../gcc-4.2.3/configure --prefix=/usr --sbindir=/usr/bin --with-local-prefix=/usr/local --enable-languages=c --enable-bootstrap --disable-nls --disable-rpath --disable-multilib --enable-shared=libgcc --disable-static --disable-libgomp --disable-libmudflap --disable-libssp --enable-linux-futex --enable-threads=posix --enable-tls --disable-symvers --with-as=/usr/bin/as --with-ld=/usr/bin/ld --without-included-gettext --without-libiconv-prefix --without-libintl-prefix --without-gmp --without-mpfr --without-system-libunwind --without-system-zlib --with-pic --without-x && make profiledbootstrap LIBCFLAGS="$CFLAGS" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" && ( make -k check | tee $SRC/build_gcc.log ; make install ) && make install DESTDIR=$R && ln -sf gcc /usr/bin/cc && ln -sf gcc $R/usr/bin/cc && INC=`gcc -print-file-name=include` && TOL=`gcc -print-file-name=install-tools` && rm {,$R}/$INC/* && cp $TOL/include/* $INC && cp $TOL/include/* $R/$INC && cp $TOL/gsyslimits.h $INC/syslimits.h && cp $TOL/gsyslimits.h $R/$INC/syslimits.h && unset INC TOL && cd $SRC && rm */ && sync && echo 'main(){}' > dummy.c && cc dummy.c -v -Wl,--verbose &> dummy.log && readelf -l a.out | fgrep '[Requesting program interpreter: /lib/ld-linux.so.2]' && fgrep 'attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/../../../crt1.o succeeded' dummy.log && fgrep 'attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/../../../crti.o succeeded' dummy.log && fgrep 'attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/../../../crtn.o succeeded' dummy.log && fgrep '#include <...> search starts here: /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/include /usr/include End of search list.' dummy.log && fgrep 'SEARCH_DIR("/usr/i686-pc-linux-gnu/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");' dummy.log && fgrep 'attempt to open /lib/libc.so.6 succeeded' dummy.log && fgrep 'found ld-linux.so.2 at /lib/ld-linux.so.2' dummy.log && rm dummy.c a.out dummy.log && echo '6-gcc' >> $SRC/build.log && sync &&
到此,最终系统的工具链核心安装完毕。
Sed
代码:
[ "`tail -1 $SRC/build.log`" = '6-gcc' ] && R=/root/sed-4.1.5/ && tar -xf sed-4.1.5.tar.gz && cd sed-4.1.5 && ./configure --prefix=/usr --sbindir=/usr/bin --enable-largefile --enable-i18n --enable-regex-tests --disable-html --disable-nls --without-included-regex --without-libiconv-prefix --without-included-gettext --without-libintl-prefix && make && make check && make install && make install DESTDIR=$R && cd $SRC && rm */ && echo '7-sed' >> $SRC/build.log && sync &&
E2fsprogs
[提示]"--disable-htree"和"--disable-debugfs"选项都会导致许多测试错误,"--disable-swapfs" 会导致lib/ext2fs测试由于找不到"tst_types"而失败,此外由于lib/ext2fs测试总是由于"Failed to allocate scratch memory!"失败,原因不明,所以这里使用sed跳过这个测试。CFLAGS和LDFLAGS必须在configure选项上设置。[依赖提示] UUID被XFS依赖,blkid,uuid 被mount/umount依赖。
代码:
R=/root/e2fsprogs-1.40.6/ && mkdir $R/{lib,etc} && tar -xf e2fsprogs-1.40.6.tar.gz && cd e2fsprogs-1.40.6 && sed -i 's:/bin/rm:rm:g' lib/blkid/test_probe.in && sed -i 's/^check::/cancelled-check::/' lib/ext2fs/Makefile.in && sed -i 's|root_sbindir=.*|root_sbindir=/usr/bin|' configure{.in,} && mkdir build && cd build && ../configure --prefix=/usr --enable-elf-shlibs --disable-profile --disable-swapfs --enable-uuidd --disable-nls --disable-rpath --with-ccopts="$CFLAGS" --with-ldopts="$LDFLAGS" --with-root-prefix=/usr --without-libiconv-prefix --without-included-gettext --without-libintl-prefix && make && make check && make install install-libs && make install install-libs DESTDIR=$R && cp /etc/blkid.tab $R/etc/ && rm {,$R}/etc/{init.d,*.old} {,$R}/usr/etc && cp /usr/lib/lib{blkid,uuid}.so.1 /lib && cp $R/usr/lib/lib{blkid,uuid}.so.1 $R/lib && cd $SRC && rm */ && echo '8-e2fsprogs' >> $SRC/build.log && sync &&
Coreutils
运行 make check 的非特权用户要求至少位于两个不同的组中,因此这里将 pgsql 用户临时添加到 dummy 组内。"RUN_VERY_EXPENSIVE_TESTS=yes"用于运行更多的测试项目。[说明]因为test-getaddrinfo测试总是由于缺乏DNS支持而失败,需要跳过它。[说明]由于Findutils包内的 xargs 程序将 echo 程序硬编码为"/bin/echo",且不能在源代码中将其修改为"echo"(会导致测试失败,原因不明),另一方面echo也是bash的内置命令,所以就将它也安装在 /bin 目录下。
代码:
R=/root/coreutils-6.10/ && mkdir $R/bin/ && tar -xf coreutils-6.10.tar.gz && cd coreutils-6.10 && patch $SRC/coreutils-6.10-i18n-1.patch && chmod +x tests/sort/sort-mb-tests && sed -i '/(setuid_root_mode)/s/(installed_su)/&;/' src/Makefile.in && echo 'int main (void) { return 0; }' > gnulib-tests/test-getaddrinfo.c && sed -i 's|HOME|& /dev/shm|' tests/other-fs-tmpdir && sed -i 's:/bin/rmdir:rmdir:g' lib/rmdir.c && ./configure --prefix=/usr --sbindir=/usr/bin --enable-option-checking --disable-acl --disable-assert --disable-rpath --enable-largefile --disable-nls --enable-install-program="arch,hostname,su" --without-libiconv-prefix --without-included-regex --without-libintl-prefix && make && make check-root NON_ROOT_USERNAME=pgsql && echo "dummy::1689:pgsql" >> /etc/group && chown pgsql gnulib-tests/.deps && su -c'make check RUN_EXPENSIVE_TESTS=yes RUN_VERY_EXPENSIVE_TESTS=yes' -s/bin/bash pgsql && sed -i '/dummy/d' /etc/group && make install install-root && cp /usr/bin/{echo,false,mktemp,sync} /bin/ && make install install-root DESTDIR=$R && cp $R/usr/bin/{echo,false,mktemp,sync} $R/bin/ && cd $SRC && rm */ && echo '9-coreutils' >> $SRC/build.log && sync &&
M4
[依赖提示]至少被Bison/Autoconf/Automake/Flex依赖
代码:
R=/root/m4-1.4.10/ && tar -xf m4-1.4.10.tar.bz2 && cd m4-1.4.10 && ./configure --prefix=/usr --sbindir=/usr/bin --disable-changeword --without-included-regex && make && make check && make install && make install DESTDIR=$R && cd $SRC && rm */ && echo '10-m4' >> $SRC/build.log && sync &&
Bison
[依赖提示]至少被Bash依赖
代码:
R=/root/bison-2.3/ && tar -xf bison-2.3.tar.bz2 && cd bison-2.3 && ./configure --prefix=/usr --sbindir=/usr/bin --disable-gcc-warnings --enable-yacc --disable-nls --disable-rpath --without-libiconv-prefix --without-libintl-prefix && make && make check && make install && make install DESTDIR=$R && cd $SRC && rm */ && echo '11-bison' >> $SRC/build.log && sync &&
Libtool
[依赖提示]至少XFS的安装依赖于它。
代码:
R=/root/libtool-1.5.26/ && tar -xf libtool-1.5.26.tar.gz && cd libtool-1.5.26 && ./configure --prefix=/usr --sbindir=/usr/bin --enable-ltdl-install --enable-shared --with-pic && make && make check && make install && make install DESTDIR=$R && cd $SRC && rm */ && echo '12-libtool' >> $SRC/build.log && sync &&
Ncurses
这个包的配置选项简直多如牛毛,这里没有(也没必要)涵盖全部选项。更多安装信息请查看源码树目录下的 INSTALL 文件(所有选项皆有描述,不需要查看 configure 的内容)。Ncurses 的测试套件与大多数包不同,不能用简单的非交互式"make check"来测试,因为 Ncurses 牵涉到视觉效果,所以必须是交互式的测试,更多有关如何测试的细节,请查看源码树下的 test/README 文件。更多官方补丁请查看:ftp://invisible-island.net/ncurses/5.6/ 。[提示]--enable/disable-database都将导致编译失败,不能使用。--disable-ext-funcs --disable-tparm-varargs 将导致 Procps 无法编译。如果你不想安装terminfo数据库可以使用"--disable-database --without-terminfo-dirs",如果你不想安装实用程序可以使用"--without-progs"。可以使用"make install.libs"仅安装共享库。
代码:
R=/root/ncurses-5.6/ && mkdir $R/lib/ && tar -xf ncurses-5.6.tar.gz && cd ncurses-5.6 && bunzip2 -kf ../ncurses-5.6-20071201-patch.sh.bz2 && chmod +x ../ncurses-5.6-20071201-patch.sh && ../ncurses-5.6-20071201-patch.sh && ./configure --prefix=/usr --sbindir=/usr/bin --without-cxx --without-cxx-binding --with-progs --without-curses-h --disable-mixed-case --without-libtool --with-shared --without-normal --without-debug --without-profile --without-termlib --without-ticlib --without-gpm --without-dlsym --without-sysmouse --disable-rpath --enable-overwrite --with-database=misc/terminfo.src --without-hashed-db --without-fallbacks --with-terminfo-dirs=/usr/share/terminfo --with-default-terminfo-dir=/usr/share/terminfo --enable-big-core --enable-big-strings --disable-termcap --without-termpath --disable-getcap --disable-getcap-cache --disable-home-terminfo --disable-root-environ --enable-symlinks --disable-broken_linker --disable-bsdpad --enable-widec --enable-lp64 --enable-largefile --enable-tparm-varargs --without-caps --with-ospeed=int --without-rcs-ids --enable-ext-funcs --enable-const --enable-no-padding --enable-signed-char --enable-sigwinch --enable-tcap-names --without-develop --disable-hard-tabs --disable-xmc-glitch --enable-assumed-color --enable-hashmap --disable-colorfgbg --disable-ext-colors --disable-ext-mouse --disable-reentrant --disable-safe-sprintf --disable-wgetch-events --enable-echo --enable-warnings --disable-assertions --without-dmalloc --without-dbmalloc --without-valgrind --enable-leaks --disable-expanded --enable-macros --without-trace && make install && cp /usr/lib/libncursesw.so.5 /lib/ && make install DESTDIR=$R && cp $R/usr/lib/libncursesw.so.5 $R/lib/ && cd $SRC && rm */ && echo '13-ncurses' >> $SRC/build.log && sync &&
Procps
Procps 的测试套件与 Ncurses 类似,由于牵涉到视觉效果,因此也是交互式测试,具体细节请查看 README 文件。
代码:
R=/root/procps-3.2.7/ && tar -xf procps-3.2.7.tar.gz && cd procps-3.2.7 && sed -i 's:<curses.h>:<ncurses.h>:' {dummy,top}.c && sed -r -i -e'/CURSES/s/-lncurses/-lncursesw/' -e's|DESTDIR\)/s?bin/|DESTDIR)/usr/bin/|' -e's|DESTDIR\)(/usr)?/\$\(lib64\)/|DESTDIR)/usr/lib/|' Makefile && make install CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" && make install DESTDIR=$R && cd $SRC && rm */ && echo '14-procps' >> $SRC/build.log && sync &&
Perl
Perl的测试很奇怪,有时候第一次运行失败,再运行一次却能成功。
代码:
R=/root/perl-5.8.8/ && tar -xf perl-5.8.8.tar.bz2 && cd perl-5.8.8 && sed -i 's/command /command[ -]/' makedepend.SH && ./configure.gnu --prefix=/usr -Dpager="/usr/bin/less -isR" && make && ( make test || make test ) && make install && make install DESTDIR=$R && rm /etc/{protocols,services} && cd $SRC && rm */ && echo '15-perl' >> $SRC/build.log && sync &&
Readline
由于只需要共享库,因此只编译和安装共享库(包括头文件)。"bash_cv_func_ctype_nonascii=yes"用于修正当en_US.ISO8859-1这个locale不存在时会出现的问题
代码:
R=/root/readline-5.2/ && mkdir $R/{etc,lib} && tar -xf readline-5.2.tar.gz && cd readline-5.2 && patch $SRC/readline-5.2-fixes-5.patch && ./configure --prefix=/usr --sbindir=/usr/bin --enable-multibyte --enable-shared --disable-static --with-curses --without-purify bash_cv_func_ctype_nonascii=yes && make shared SHLIB_LIBS=-lncursesw SHOBJ_CFLAGS="$CFLAGS -fpic" SHOBJ_LDFLAGS="$LDFLAGS -shared" && make install-shared && cp /usr/lib/lib{history,readline}.so.5 /lib/ && make install-shared DESTDIR=$R && cp $R/usr/lib/lib{history,readline}.so.5 $R/lib/ && echo 'set horizontal-scroll-mode Off set meta-flag On set input-meta On set convert-meta Off set output-meta On set bell-style none "\eOd": backward-word "\eOc": forward-word "\e[1~": beginning-of-line "\e[4~": end-of-line "\e[5~": beginning-of-history "\e[6~": end-of-history "\e[3~": delete-char "\e[2~": quoted-insert' | tee {,$R}/etc/inputrc && cd $SRC && rm */ && echo '16-readline' >> $SRC/build.log && sync &&
Zlib
由于只需要共享库,因此只编译和安装共享库(包括头文件)。[提示]configure脚本只传递了CFLAGS而未传递LDFLAGS,因此需要在配置完毕后(不能提前修改Makefile.in,configure会覆盖掉你的修改)再修改Makefile中的LDSHARED(作用于共享库)和 LDFLAGS(作用于二进制文件)。
代码:
R=/root/zlib-1.2.3/ && mkdir $R/lib/ && tar -xf zlib-1.2.3.tar.bz2 && cd zlib-1.2.3 && sed -i 's/${CFLAGS-"-fPIC -O3"}/"${CFLAGS-"-O3"} -fPIC"/' configure && ./configure --prefix=/usr --shared && sed -i -e"s|^LDSHARED=.*|& $LDFLAGS|" -e"s|^LDFLAGS=.*|& $LDFLAGS|" Makefile && make && make check && make install && cp /usr/lib/libz.so.1 /lib/ && make install