LFS 记录一下
时间:2009-03-24 来源:xinxian.can
我算准了时间,昨天,今天,直到下班一个小时,我用两天的时间搞了一个LFS,两天前有过三次失败(在同一天内),不算。呵呵,特记录与此,没有详细的步骤与说明,只不过是把我敲的命令给记录下下了。
我在此参考了 官方 文档 与 耐心的人(我暂且这样称呼他吧,写的太认真了)
创建分区,并在分区上新建 必要的目录,例如tools source soft 等。
挂载
添加 lfs用户并设置其环境
.bash_profile
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
前面的步骤省略掉,可以参考官方的文档。
Binutils 是一组开发工具,包括连接器、汇编器和其他用于目标文件和档案的工具。
make -C ld clean
make -C ld LIB_PATH=/tools/lib
cp -v ld/ld-new /tools/bin
make 参数的含义:
-C ld clean
告诉 make 程序删除所有 ld 子目录中编译生成的文件。
-C ld LIB_PATH=/tools/lib
这个选项重新编译 ld 子目录中的所有文件。在命令行中指定 Makefile 的 LIB_PATH 变量值,使它明确指向临时工具目录,以覆盖默认值。这个变量的值指定了连接器的默认库搜索路径,它在这一章的稍后部分会用到。
GCC 软件包包含 GNU 编译器集合,其中有 C 和 C++ 编译器。
mkdir -v ../gcc-build
cd ../gcc-build
为编译 GCC 做准备:
../gcc-4.0.3/configure --prefix=/tools \
--with-local-prefix=/tools --disable-nls --enable-shared \
--enable-languages=c
make bootstrap
bootstrap
使用这个参数的目的不仅仅是编译 GCC ,而是重复编译它几次。它用第一次编译生成的程序来第二次编译自己,然后又用第二次编译生成的程序来第三次编译自己,最后比较第二次和第三次编译的结果,以确保编译器能毫无差错的编译自身,这通常表明编译是正确的。
make install
最后,我们创建一个必要的符号连接。因为许多程序和脚本试图运行 cc 而不是 gcc ,这样做是为了让程序能在多种 Unix 平台上运行,并保持一致性。并不是每个人都安装 GNU C 编译器。只运行 cc 而不是 gcc 可以把选择 C 编译器的自由留给系统管理员,我们这里将指向 gcc :
ln -vs gcc /tools/bin/cc
Glibc-2.5.1
代码:
tar xvf /lfs-sources/glibc-2.5.1.tar.bz2
cd glibc-2.5.1
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.5.1/configure --prefix=/tools \ --disable-profile --enable-add-ons \ --enable-kernel=2.6.0 --with-binutils=/tools/bin \ --without-gd --with-headers=/tools/include \ --without-selinux
make
mkdir -v /tools/etc
touch /tools/etc/ld.so.conf
make install
cd ..
rm -rf glibc-build
rm -rf glibc-2.5.1
测试工具安装
说明:这部分将安装3个用于第六章各种源码包编译后的测试的工具,所以如果你不打算做make check之类的事情,那么这3个包可以不装。
Tcl-8.4.15 Expect-5.43.0 DejaGNU-1.4.4
cd unix
./configure --prefix=/tools
make
make install
make install-private-headerrs
ln -sv tclsh8.4 /tools/bin/tclsh
安装 Expect
先修正一个可能导致 GCC 测试程序假失败的 bug :
patch -Np1 -i ../expect-5.43.0-spawn-1.patch
为编译 Expect 做准备:
./configure --prefix=/tools --with-tcl=/tools/lib \
--with-tclinclude=/tools/include --with-x=no
配置选项的含义:
--with-tcl=/tools/lib
这个选项确保配置脚本找到的是安装在临时工具目录下的 Tcl ,而不是宿主系统里的。
--with-tclinclude=/tools/include
这个选项告诉 Expect 到哪里寻找 Tcl 的源代码目录和头文件。使用这个选项可以避免 configure 脚本因为找不到 Tcl 的源代码目录而导致的失败。
--with-x=no
这个选项告诉 configure 脚本不要搜索 Tk(Tcl的图形界面组件)或者 X Window 系统的库,这两者都可能位于宿主系统上。
编译软件包:
make
要测试结果,请运行:make test 。请注意,已知 Expect 的测试程序会在某些不在我们控制范围内的宿主系统下出现测试失败。因此,如果您运行这里的测试程序失败了也没关系,因为这并不关键。
安装软件包:
make SCRIPTS="" install
make 参数的含义:
SCRIPTS=""
这个选项防止安装 Expect 所补充的一些并不需要的脚本。
安装 DejaGNU
为编译 DejaGNU 做准备:
./configure --prefix=/tools
编译并安装软件包:
make install
要测试结果,请运行:make check 。
gcc pass 2
cp -v gcc/Makefile.in{,.orig} &&
sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig > gcc/Makefile.in
cp -v gcc/Makefile.in{,.tmp} &&
sed 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \
> gcc/Makefile.in
patch -Np1 -i ../gcc-4.0.3-specs-1.patch
mkdir -v ../gcc-build
cd ../gcc-build
../gcc-4.0.3/configure --prefix=/tools \
--with-local-prefix=/tools --enable-clocale=gnu \
--enable-shared --enable-threads=posix \
--enable-__cxa_atexit --enable-languages=c,c++ \
--disable-libstdcxx-pch
make
make install
echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'
如果一切正常,应该不会出错,而且最后一个命令的结果应当是:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
重新安装 Binutils
再次为编译创建一个单独目录:
mkdir -v ../binutils-build
cd ../binutils-build
为编译 Binutils 做准备:
../binutils-2.16.1/configure --prefix=/tools \
--disable-nls --with-lib-path=/tools/lib
make
make install
为下一章的"再次调整工具链"阶段配置连接器:
make -C ld clean
make -C ld LIB_PATH=/usr/lib:/lib
cp -v ld/ld-new /tools/bin
Ncurses 提供独立于终端的字符终端处理库,含有功能键定义(快捷键)、屏幕绘制以及基于文本终端的图形互动功能。
./configure --prefix=/tools --with-shared \
--without-debug --without-ada --enable-overwrite
--without-ada
这个选项让 Ncurses 在即使宿主系统上安装了 Ada 编译器的情况下也不要编译其 Ada 绑定。需要这样做的原因是一旦我们进入 chroot 环境,Ada 就不能使用了。
--enable-overwrite
这个选项让 Ncurses 把它的头文件安装到 /tools/include 目录,而不是 /tools/include/ncurses 目录,以确保其它软件包可以顺利找到 Ncurses 的头文件。
make
make install
patch -Np1 -i ../bash-3.1-fixes-8.patch
为编译 Bash 做准备:
./configure --prefix=/tools --without-bash-malloc
配置选项的含义:
--without-bash-malloc
这个选项禁用了 Bash 的内存分配函数(malloc),这个函数已知会造成段错误,通过设置这个选项,Bash 将使用更为稳定的 Glibc 里的 malloc 函数。
make
make install
ln -vs bash /tools/bin/sh
安装 Bzip2
Bzip2 软件包没有 configure 脚本,用下面的命令直接编译:
make
安装软件包:
make PREFIX=/tools install
Coreutils 软件包包括一整套用于显示和设置基本系统特征的工具。
./configure --prefix=/tools
make
make install
cp -v src/su /tools/bin/su-tools
Diffutils 软件包里的程序可以向你显示两个文件或目录的差异,常用来生成软件的补丁。
./configure --prefix=/tools
make
make install
Findutils 软件包包含查找文件的工具,既能即时查找(递归的搜索目录,并可以显示、创建和维护文件),也能在数据库里查找(通常比递归查找快但是在数据库没有及时更新的情况下,结果并不可靠)。
./configure --prefix=/tools
make
make install
安装 Gawk
为编译 Gawk 做准备:
./configure --prefix=/tools
由于 configure 脚本的一个 bug ,Gawk 不能正确检测某些 Glibc 支持的 locale ,这将会导致一些问题,比如,Gettext 的测试程序会失败。修复这个 bug 的办法是在 config.h 文件结尾追加丢失的宏定义:
cat >>config.h <<"EOF"
#define HAVE_LANGINFO_CODESET 1
#define HAVE_LC_MESSAGES 1
EOF
编译软件包:
make && make installl
为编译 Grep 做准备:
./configure --prefix=/tools \
--disable-perl-regexp
配置选项的含义:
--disable-perl-regexp
这个选项确保 grep 程序不连接可能在宿主系统上存在的 PCRE(Perl 兼容正则表达式)库,因为进入 chroot 环境后,它就不能使用了。
make
make install
安装 Gzip
为编译 Gzip 做准备:
./configure --prefix=/tools
编译软件包:
make
这个软件包没有附带测试程序。
安装软件包:
make install
安装 M4
为编译 M4 做准备:
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
安装 Make
为编译 Make 做准备:
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
安装 Patch
为编译 Patch 做准备:
./configure --prefix=/tools
编译软件包:
make
这个软件包没有附带测试程序。
安装软件包:
make install
Perl 是 Practical Extraction and Report Language的缩写。Perl 将 C, sed, awk 和 sh 的最佳特性集于一身,是一种强大的编程语言。
首先应用下面的补丁,调整指向 C 库的硬连接路径:
patch -Np1 -i ../perl-5.8.8-libc-2.patch
准备编译 Perl(请正确输入下面命令中的'Data/Dumper Fcntl IO POSIX'——全是字母):
./configure.gnu --prefix=/tools -Dstatic_ext='Data/Dumper Fcntl IO POSIX'
配置选项的含义:
-Dstatic_ext='Data/Dumper Fcntl IO POSIX'
这个选项让 Perl 编译静态扩展的最小集,下一章安装和测试 Coreutils 软件包的时候需要用到。
仅需要编译这个软件包中的一小部分必要工具:
make perl utilities
尽管 Perl 附带测试程序,但我们不推荐在这里运行。由于只编译了一部分 Perl,现在运行 make test 会编译 Perl 的其余部分,而这里我们并不需要它们。如果想测试的话,可以到下一章再运行测试程序。
安装这些工具和库:
cp -v perl pod/pod2man /tools/bin
mkdir -pv /tools/lib/perl5/5.8.8
cp -Rv lib/* /tools/lib/perl5/5.8.8
sed 是一个流编辑程序,在一个输入流(从一个文件或者一个管道的输入)上进行基本的文本编辑操作。
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
Tar 软件包含有一个归档程序,用来保存文件到归档文件或者从给定的 tar 归档文件中释放文件。
./configure --prefix=/tools
make
make install
cd ..
rm -rf tar-1.18
Texinfo 软件包包含读取、写入和转换 Info 文档的程序,以提供系统文档。
./configure --prefix=/tools
make && make install
Texinfo 软件包包含读取、写入和转换 Info 文档的程序,以提供系统文档。
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理驱动器,以及打开 tty 端口和处理消息。
Util-linux 默认不使用刚才安装在 /tools 目录下的头文件和库文件,我们更改配置脚本来修正这个问题:
sed -i 's@/usr/include@/tools/include@g' configure
为编译 Util-linux 做准备:
./configure
编译一些支持例程:
make -C lib
我们只需要这个软件包中的少数几个工具,因此只需要编译这几个工具就可以了:
make -C mount mount umount
make -C text-utils more
这个软件包没有附带测试程序。
把这些程序复制到临时工具目录:
cp mount/{,u}mount text-utils/more /tools/bin
清理系统 不做
6.2. 挂载虚拟内核文件系统
虚拟内核文件系统(Virtual Kernel File Systems),是指那些是由内核产生但并不存在于硬盘上(存 在于内存中)的文件系统,他们被用来与内核进行通信。
首先让我们为虚拟内核文件系统建立挂载目录:
mkdir -pv $LFS/{dev,proc,sys}
6.2.1. 创建初始设备节点
内核在引导时要求某些设备节点必须存在(特别是 console 和 null ),这些设备节点必须创建在硬盘 上才能使得内核在 udev 尚未启动之前就可以使用它们,此外还有当Linux以init=/bin/bash 启动。使用下面的命令来创建这些节点:
mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3
6.2.2.挂载并填充 /dev 目录
推荐的向 /dev 目录填充设备的方法是在 /dev 上挂载一个虚拟文件系统(比如 tmpfs),然后在设备 被检测到或被访问到的时候(通常是在系统引导的过程中)动态创建设备节点。既然现在新的系统尚未被引导, 那么就有必要通过手工挂载和填充 /dev 目录。这可以通过绑定挂载宿主系统的 /dev 目录。绑定挂载是一种 特殊的挂载方式,允许你创建一个目录或者是挂载点的镜像到其他的地方。可以使用下面的命令:
mount --bind /dev $LFS/dev
6.2.3. 挂载虚拟内核文件系统
现在挂载虚拟内核文件系统:
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
现在将要进入 chroot 环境开始编译安装最终的 LFS 系统了,注意:在这里我们只使用临时构建的工具。以 root 身份运行以下命令进入构建环境:
chroot "$LFS" /tools/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/tools/bin/bash --login +h
env 命令的参数 -i 的作用是清除所有 chroot 环境变量。后面是重新设定 HOME, TERM, PS1, PATH 等变量的值。TERM=$TERM 设定虚拟根环境中的 TERM 的值与 chroot 外面的一样。这个值是让像 vim 和 less 之类的程序可以正确操作。如果还需要重新设置其它的值,如 CFLAGS 或 CXXFLAGS ,这里是个不错的位置。
从这里开始,不再需要 LFS 环境变量了,因为所有的工作都被限制在 LFS 文件系统里面。这是由于已经告诉了 Bash shell $LFS 是现在的根目录(/)。
注意,这里 /tools/bin 位于 PATH 的最后面。也就是说当软件包的最终版本安装之后就不再使用临时工具了。为了使 shell 无法"记住"可执行二进制代码的位置,需要通过使用 +h 参数关闭 bash 的散列功能。
注意此时 bash 提示符会显示:I have no name! 这是正常的,因为 /etc/passwd 还没有创建。
现在我们在 LFS 分区中创建目录树结构,用下列命令能创建一个标准的目录树:
mkdir -pv /{bin,boot,etc/opt,home,lib,mnt,opt}
mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
for dir in /usr /usr/local; do
ln -sv share/{man,doc,info} $dir
done
mkdir -v /var/{lock,log,mail,run,spool}
mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
缺省的目录的权限模式为 755,但也并非所有的目录都如此。以上的命令有两处有所不一样:一个是 root 用户的目录,另外两个是临时文件目录。
第一个权限模式的不同之处是确保禁止任何人进入到 /root 目录中——同样的,这个模式也适用于让其它的普通用户可以工作在自己的目录中。第二个权限模式的不同之处是确保所有用户都可以写 /tmp 和 /var/tmp 目录,但不能从中删除其它用户的文件,这是由"sticky位",也就是"1777"中的"1"来设定的。
6.5.1. FHS 兼容性说明
我们的目录树是按照 FHS(Filesystem Hierarchy Standard) 标准(http://www.pathname.com/fhs/)。除了上面创建的目录外,该标准还规定了必须有 /usr/local/games 和 /usr/share/games 两个目录,但是作为一个基本系统,我们并不需要这些。如果你要完全的遵守 FHS 标准的话,就自己建立这两个目录。至于 /usr/local/share 目录下的子目录,FHS 标准规定得并不严格,所以我们就创建了(在我们看来)需要的子目录。
创建必需的文件与符号连接
一些程序使用固化的路径(hard-wired paths)指向一些目前还不存在的程序上。为了兼容这些程序,可以创建一些符号链接,然后在软件安装之后用实际文件进行替代。
ln -sv /tools/bin/{bash,cat,grep,pwd,stty} /bin
ln -sv /tools/bin/perl /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv bash /bin/sh
一个常规的Linux系统在/etc/mtab中有一个已挂载文件系统的列表。 正常情况下,这个文件在我们挂载一个新的文件系统的时候会被创建。因为我们在chroot环境下不会再挂载任何文件系统 ,所以我们需要为那些用到/etc/mtab的程序创建一个空文件:
touch /etc/mtab
为了让 root 用户可以登录而且用户名"root"可以被识别,在这里需要创建相应的 /etc/passwd 和 /etc/group 文件。
使用下面的命令创建 /etc/passwd 文件:
cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
EOF
root 的真正密码将在后面设置("x"在这里只是一个占位符)。
下面的命令创建 /etc/group 文件:
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
tape:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
EOF
这里创建的用户组并不是某个标准所要求的部分,只是因为在随后 Udev 配置将要用到而以。Linux 标准基础(LSB, Linux Standard Base, http://www.linuxbase.org) 只是推荐"root"组的 GID 为 0,另一个组"bin"的 GID 为 1 。其它所有的组名和 GID 均由系统管理员自由设定,因为比较好的软件包一般都不依赖于 GID ,而只是使用组名。
因为完整的 Glibc 在Chapter 5中已经安装,而且 /etc/passwd 和 /etc/group 文件也已创建,用户名和组名现在可以开始使用了。现在启动新的shell,驱除"I have no name!"提示符:
exec /tools/bin/bash --login +h
注意这里使用了 +h 参数。这是告诉 bash 不能使用其内部哈希表查找路径。如果没有使用这个参数,则 bash 将会记住已经执行的二进制代码的路径。为了让新编译安装的二进制代码可以马上投入使用,在这一章中,我们使用 +h 关闭了此功能。
程序 login, agetty, init (还有其它一些程序) 使用一些日志文件来记录信息,比如谁在什么时候登录了系统等等。然而如果这些日志文件不存在,这些程序则无法写入。下面初始化这些日志文件,并设置适当的权限:
touch /var/run/utmp /var/log/{btmp,lastlog,wtmp}
chgrp -v utmp /var/run/utmp /var/log/lastlog
chmod -v 664 /var/run/utmp /var/log/lastlog
/var/run/utmp 记录着现在登录的用户。/var/log/wtmp 记录所有的登录和退出。/var/log/lastlog 记录每个用户最后的登录信息。/var/log/btmp 记录错误的登录尝试
从现在开始一直到第六章的Stripping Again之前,这个阶段如果你关机或重新启动,那么重新开机后回到工作状态的步骤是:
1.重新启动计算机,并从LiveCD启动
2.加载分区
export LFS=/mnt/lfs
mkdir -pv $LFS
mount /dev/hda2 $LFS
3.加载交换分区(如果不想用交换分区或者没有交换分区可跳过此步骤)
swapon /dev/hda1
4.加载必要的文件系统
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
5.Chroot到目标系统下
chroot "$LFS" /tools/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/bin/bash --login +h
6.进入编译目录
cd /sources
export LFS=/sources
安装头文件
cp ../sources/linux-2.6.22.5.tar.bz2 ./
tar xjvf linux-2.6.22.5.tar.bz2
cd linux-2.6.22.5
sed -i '/scsi/d' include/Kbuild
make mrproper
make headers_check
make INSTALL_HDR_PATH=dest headers_install
cp -rv dest/include/* /usr/include
cd ..
rm -rf linux-2.6.22.5* -rf
安装 Man-pages
使用下述命令安装 Man-pages :
make install
在进行之前请检查一下是否glibc-2.5.1和glibc-build这两个目录已经被删除,如果没有删除请删除后在继续。
cd glibc-2.5.1
tar -xvf $LFS/glibc-libidn-2.5.1.tar.gz
mv glibc-libidn-2.5.1 libidn
sed -i '/vi_VN.TCVN/d' localedata/SUPPORTED
sed -i \
's|libs -o|libs -L/usr/lib -Wl,-dynamic-linker=/lib/ld-linux.so.2 -o|' \
scripts/test-installation.pl
sed -i 's|@BASH@|/bin/bash|' elf/ldd.bash.in
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.5.1/configure --prefix=/usr \
--disable-profile --enable-add-ons \
--enable-kernel=2.6.0 --libexecdir=/usr/lib/glibc
make
make -k check 2>&1 | tee glibc-check-log
grep Error glibc-check-log
touch /etc/ld.so.conf
make install
make localedata/install-locales将安装全部的locale,如果你不想装这么多locale的话就用localedef命令来安装,LFS手册上有例子,如果仅想加入中文的locale,就用
mkdir -pv /usr/lib/locale
localedef -i zh_CN -f GB18030 zh_CN
localedef -i zh_CN -f GBK zh_CN
localedef -i zh_CN -f UTF-8 zh_CN
localedef -i zh_CN -f GB2312 zh_CN
localedef -i zh_HK -f UTF-8 zh_CN
localedef -i zh_HK -f BIG5-HKSCS zh_CN
localedef -i zh_TW -f EUC-TW zh_CN
localedef -i zh_TW -f UTF-8 zh_CN
建立几个重要文件:
代码:
cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF
cp -v --remove-destination /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
cat > /etc/ld.so.conf << "EOF"
/usr/local/lib
/opt/lib EOF
删除编译目录
代码:
cd .. rm -rf glibc-build rm -rf glibc-2.5.1
相关知识:
glibc的测试比较容易出现错误,比如机器慢就有可能出现超时的错误,还有一些能引起错误的LFS手册上有所提及,像超时这种错误有时候很难避免,就跳过去吧。
再次调整工具链
mv -v /tools/bin/{ld,ld-old}
mv -v /tools/i686-pc-linux-gnu/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/i686-pc-linux-gnu/bin/ld
接下来,修正 GCC 的 specs 文件,使它指向新的动态链接器,这样 GCC 才能知道在哪能发现开始文件。应用一个 perl 命令:
gcc -dumpspecs | \
perl -p -e 's@/tools/lib/ld-linux.so.2@/lib/ld-linux.so.2@g;' \
-e 's@\*startfile_prefix_spec:\n@$_/usr/lib/ @g;' > \
`dirname $(gcc --print-libgcc-file-name)`/specs
修改之后,用你的眼睛亲自检查一下 specs 文件,确保已经改正确了。
重要
如果你的系统平台上,动态连接器的名字不是 ld-linux.so.2 ,你必须把上面命令里的"ld-linux.so.2"换成你的系统平台上动态连接器的名字
现在有必要停下来,检查一下新工具链的基本功能(编译和连接)是否正常,我们进行一个简单的合理性检查:
echo 'main(){}' > dummy.c
cc dummy.c -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):
[Requesting program interpreter: /lib/ld-linux.so.2]
注意,/lib 应该是动态连接器的前缀。
现在确保我们设置使用正确的开始文件:
grep -o '/usr/lib.*/crt[1in].* .*' dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded
接下来要做的是验证新的链接器是否在正确的搜索路径内:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib");
下面,确保我们是否正在使用正确的 libc:
grep "/lib/libc.so.6 " dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
attempt to open /lib/libc.so.6 succeeded
最后,确保 GCC 正在使用正确的动态链接器:
grep found dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):
found ld-linux.so.2 at /lib/ld-linux.so.2
如果输出与上面不同或者没有输出,那么就有大问题了。你需要检查一下前面的操作,看看问题出在哪里,并改正过来。在改正之前,不要继续后面的部份,因为没什么意义。大多数情况下,出错都是因为上面的 specs 文件没改对。当然,如果你的平台上动态连接器的名字不是 ld-linux.so.2 ,上面的结果也会不同。在继续之前要解决所有的问题。
在确定一切正常后,删除测试文件:
rm -v dummy.c a.out dummy.log
Binutils-2.17
代码:
tar xvf $LFS/binutils-2.17.tar.bz2
mkdir binutils-build
cd binutils-build
../binutils-2.17/configure --prefix=/usr --enable-shared
make tooldir=/usr
测试:
代码:
make check
这里测试统计可能会出现个别失败。
代码:
make tooldir=/usr install
cp -v ../binutils-2.17/include/libiberty.h /usr/include
cd ..
rm -rf binutils-build binutils-2.17
安装 GCC
使用一个 sed 命令来禁止 GCC 安装它自己的 libiberty.a 。我们将使用 Binutils 附带的 libiberty.a 来代替:
sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in
在节 5.4, "GCC-4.0.3 - 第一遍" 中应用的 bootstrap 编译中,编译器会有 -fomit-frame-pointer 的标志。非bootstrap编译默认是忽略这个标志的,可以应用下面的sed 命令来确保编译的可靠性。
sed -i 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in
fixincludes 脚本偶尔会因为修改系统的头文件而出错。因为GCC-4.0.3 和 Glibc-2.3.6 是不需要修改的,运行下面的命令可以避免 fixincludes 脚本运行:
sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in
GCC 中提供了一个 gccbug 脚本,会在编译时侦测 mktemp 是否存在,并且在测试中加强代码。这将会导致脚本使用一些不算很随机的名字来命名临时文件。因为我们后面会安装 mktemp ,这里我们就模仿它的存在:
sed -i 's/@have_mktemp_command@/yes/' gcc/gccbug.in
GCC 的安装指南推荐用一个新建的目录来编译它,而不是在源码目录中:
mkdir -v ../gcc-build
cd ../gcc-build
为编译 GCC 做准备:
../gcc-4.0.3/configure --prefix=/usr \
--libexecdir=/usr/lib --enable-shared \
--enable-threads=posix --enable-__cxa_atexit \
--enable-clocale=gnu --enable-languages=c,c++
编译软件包:
make
[Important]
重要
本节的GCC测试套件很重要。在任何情况下都不要省略这一步。
运行测试套件,但遇到错误不停止(你还记得那些老是出错的测试吧):
make -k check
要查看测试单元的测试结果,可以运行:
../gcc-4.0.3/contrib/test_summary
如果只想看概要,可以把输出通过管道传递给 grep -A7 Summ 。
结果可以跟 http://www.linuxfromscratch.org/lfs/build-logs/6.2/ 的进行比较。
一些预想不到的错误总是无法避免的。虽然GCC的开发者经常留意这些问题,但是有些还是没有得到解决。通常,libmudflap 测试尤其被认为是有问题的(这是一个bug,参见http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20003)。 除非测试结果给上面URL的有很多不同,一般是可以安全继续的。
安装软件包:
make install
有的软件包希望 C PreProcessor(预处理器)安装在 /lib 目录下,为了满足它们的要求,我们创建如下符号链接:
ln -sv ../usr/bin/cpp /lib
许多软件包使用 cc 作为 C 编译器的名字,为了满足它们的要求,创建如下符号链接:
ln -sv gcc /usr/bin/cc
现在,我们的最终工具链已经形成了,我们需要做的就是确保编译、链接按照我们希望的完成。我们可以通过本章前面的简册方法来实现:
echo 'main(){}' > dummy.c
cc dummy.c -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
如果所有的都工作正常,就不会有错误,并且命令的输出应该是(允许不同平台的动态链接器的名称不同):
[Requesting program interpreter: /lib/ld-linux.so.2]
现在确保我们使用正确的 startfiles:
grep -o '/usr/lib.*/crt[1in].* .*' dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是:
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crtn.o succeeded
接下来,确认新的链接器被应用到了正确的搜索路径中:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
如果所有的都工作正常,就不会有错误,并且命令的输出应该是:
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
现在,确保我们正在使用正确的 libc :
grep "/lib/libc.so.6 " dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是
attempt to open /lib/libc.so.6 succeeded
最后,确保 GCC 正在使用正确的动态链接器:
grep found dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是(允许不同平台的动态链接器的名称不同):
found ld-linux.so.2 at /lib/ld-linux.so.2
如果输出不是像上面那样或者根本没有输出,那么就有大问题了。返回并检查前面的操作,找出问题,并改正过来。最有可能的原因是上面修正 specs 文件时出错。任何一个问题都需要在继续之前解决掉。
一旦工具都工作正常,清理测试文件:
rm -v dummy.c a.out dummy.log
唉,这个花费了我一个多小时的宝贵时间。总算过去了。
Berkeley DB-4.5.20
代码:
tar xvf $LFS/db-4.5.20.tar.gz
cd db-4.5.20
patch -Np1 -i $LFS/db-4.5.20-fixes-1.patch
cd build_unix
../dist/configure --prefix=/usr --enable-compat185 --enable-cxx
make
make docdir=/usr/share/doc/db-4.5.20 install
chown -Rv root:root /usr/share/doc/db-4.5.20
cd /sources
rm -rf db-4.5.20
Coreutils 软件包包括一套显示、设置基本系统属性的工具。
cd coreutils-6.9
patch -Np1 -i $LFS/coreutils-6.9-uname-1.patch
patch -Np1 -i $LFS/coreutils-6.9-suppress_uptime_kill_su-1.patch
patch -Np1 -i $LFS/coreutils-6.9-i18n-1.patch
chmod +x tests/sort/sort-mb-tests
./configure --prefix=/usr
make
make NON_ROOT_USERNAME=nobody check-root 237
echo "dummy:x:1000:nobody" >> /etc/group
echo "dummy:x:1000:1000::/root:/bin/bash" >> /etc/passwd
make NON_ROOT_USERNAME=dummy check-root
src/su dummy -c "make RUN_EXPENSIVE_TESTS=yes check"
sed -i '/dummy/d' /etc/passwd /etc/group
安装软件包:
make install
把一些程序移动到合适的位置以符合 FHS 标准:
mv -v /usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} /bin
mv -v /usr/bin/{false,hostname,ln,ls,mkdir,mknod,mv,pwd,rm} /bin
mv -v /usr/bin/{rmdir,stty,sync,true,uname} /bin
mv -v /usr/bin/chroot /usr/sbin
一些 LFS-Bootscripts 包中的脚本依赖于 head, sleep,和 nice 。由于 /usr 目录有可能在系统启动过程的早期不可用(比如尚未挂载),所以这些二进制程序需要放置在根分区上:
mv -v /usr/bin/{head,sleep,nice} /bin
Iana-Etc 软件包提供了网络服务和协议的数据。
make && make install
M4 软件包包含一个宏处理器。
./configure --prefix=/usr
make
make check && make install
Bison-2.3
tar xvf $LFS/bison-2.3.tar.bz2
cd bison-2.3
./configure --prefix=/usr
echo '#define YYENABLE_NLS 1' >> config.h make
测试
make check
这里check不会有错
make install
cd ..
rm -rf bison-2.3
Bison 软件包包括一个语法分析程序生成器。
./configure --prefix=/usr
如果 bison 程序不在 $PATH 中的话,编译时将会出现缺乏国际化支持的错误信息。下面处理可以解决这个问题:
echo '#define YYENABLE_NLS 1' >> config.h
make && make check && make install
Ncurses 程序包提供字符终端处理库,包括面板和菜单。
cd ncurses-5.6
patch -Np1 -i $LFS/ncurses-5.6-coverity_fixes-1.patch
./configure --prefix=/usr --with-shared --without-debug --enable-widec
make
make install
chmod -v 644 /usr/lib/libncurses++w.a
mv -v /usr/lib/libncursesw.so.5* /lib
ln -sfv ../../lib/libncursesw.so.5 /usr/lib/libncursesw.so
for lib in curses ncurses form panel menu ; do \
rm -vf /usr/lib/lib${lib}.so ; \
echo "INPUT(-l${lib}w)" >/usr/lib/lib${lib}.so ; \
ln -sfv lib${lib}w.a /usr/lib/lib${lib}.a ; \
done
ln -sfv libncurses++w.a /usr/lib/libncurses++.a
rm -vf /usr/lib/libcursesw.so
echo "INPUT(-lncursesw)" >/usr/lib/libcursesw.so
ln -sfv libncurses.so /usr/lib/libcurses.so
ln -sfv libncursesw.a /usr/lib/libcursesw.a
ln -sfv libncurses.a /usr/lib/libcurses.a
cd ..
rm -rf ncurses-5.6
sed 是一个流编辑器
./configure --prefix=/usr --bindir=/bin
make && make check && make install
GNU libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一的、可移植的接口中。
./configure --prefix=/usr
make && make check && make install
perl
为了运行测试套件,要先创建一个基本的 /etc/hosts 文件,好几个测试都需要它来解析 localhost 的名称:
echo "127.0.0.1 localhost $(hostname)" > /etc/hosts
对 Perl 的设置进行更多的控制,你可以运行交互的 Configure 脚本,精心选择编译配置。如果你能接受 Perl 的自动配置(这是很明智的),就用下面的命令:
./configure.gnu --prefix=/usr \
-Dman1dir=/usr/share/man/man1 \
-Dman3dir=/usr/share/man/man3 \
-Dpager="/usr/bin/less -isR"
配置选项的含义:
-Dpager="/usr/bin/less -isR"
纠正 perldoc 代码调用 less 程序时的一个错误。
-Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3
因为 Groff 还没有安装,Configure 会认为我们不想安装 Perl 的 man 手册。应用这个参数来改变这种情况:
编译软件包:
make
要测试结果,请运行:make test 。
安装软件包:
make install
readline
cd readline-5.2
clear
sed -i '/MV.*old/d' Makefile.in
sed -i '/{OLDSUFF}/c:' support/shlib-install
patch -Np1 -i ../../sources/readline-5.2-fixes-3.patch
./configure --prefix=/usr --libdir=/lib
make SHLIB_XLDFLAGS=-lncurses
make install
mv -v /lib/lib{readline,history}.a /usr/lib
rm -v /lib/lib{readline,history}.so
ln -sfv ../../lib/libreadline.so.5 /usr/lib/libreadline.so
ln -sfv ../../lib/libhistory.so.5 /usr/lib/libhistory.so
cd ..
Zlib 软件包包含 zlib 库,很多程序中的压缩或者解压缩程序都会用到这个库。
./configure --prefix=/usr --shared --libdir=/lib
399 make
400 make check
401 make install
402 mv -v /lib/libz.so ../
403 ln -sfv ../../lib/libz.so.1.2.3 /usr/lib/libz.so
404 make clean
405 ./configure --prefix=/usr
406 make
407 make check
408 make install
409 chmod -v 644 /usr/lib/libz.a
410 cd ..
411 rm -rf zlib-1.2.3
412 history
Autoconf 能生成用于自动配置源代码的 shell 脚本
./configure --prefix=/usr
make && make install
bzip
patch -Np1 -i ../../sources/bzip2-1.0.4-install_docs-1.patch
471 make -f Makefile-libbz2_so
472 make clean
473 make
474 make PREFIX=/usr install
475 cp -v bzip2-shared /bin/bzip2
476 cp -av libbz2.so* /lib
477 ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
478 rm -v /usr/bin/{bunzip2,bzcat,bzip2}
479 ln -sv bzip2 /bin/bunzip2
480 ln -sv bzip2 /bin/bzcat
481 cd ..
482 rm -rf bzip2-1.0.4
diffutils
tar xvf diffutils-2.8.1.tar.gz
486 cd diffutils-2.8.1
487 patch -Np1 -i ../../sources/diffutils-2.8.1-i18n-1.patch
488 cat man/diff.1
489 ls -l man/diff.1
490 touch man/diff.1
491 ls -l man/diff.1
492 cat man/diff.1
493 ./configure --prefix=/usr/
494 make
495 make install
496 cd ..
497 ls
498 rm -rf diffutils-2.8.1
file
./configure --prefix=/usr
make && make install
find
./configure --prefix=/usr --libexecdir=/usr/lib/findutils \
--localstatedir=/var/lib/locate
make && make check && make install
mv -v /usr/bin/find /bin
sed -i -e 's/find:=${BINDIR}/find:=\/bin/' /usr/bin/updatedb
Flex 软件包包含一个能生成识别文本模式的程序的工具。
./configure --prefix=/usr
make && make check && make install
cd flex-2.5.33
523 ./configure --prefix=/usr
524 make
525 make check
526 make install
527 ln -sv libfl.a /usr/lib/libl.a
528 ls -l /usr/lib/libl.a
529 ls -l /usr/lib/libfl.a
530 ls libfl.a -l
531 cat > /usr/bin/lex << "EOF"
#!/bin/sh
# Begin /usr/bin/lex
exec /usr/bin/flex -l "$@"
# End /usr/bin/lex
EOF
532 chmod -v 755 /usr/bin/lex
GRUB 程序包包含 GRand 统一引导装载程序。
cd grub-0.97
patch -Np1 -i $LFS/grub-0.97-disk_geometry-1.patch
./configure --prefix=/usr
make && make check
make install
mkdir -v /boot/grub
cp -v /usr/lib/grub/i386-pc/stage{1,2} /boot/grub
把 i386-pc 换成适合你的平台的路径。
i386-pc 目录还包含一些 *stage1_5 文件,是为不同的文件系统准备的。看看有哪些文件,并把你所需要的拷贝到 /boot/grub 目录下。多数人需要 e2fs_stage1_5 和/或 reiserfs_stage1_5 文件。
Gawk 软件包包含用于管理文本文件的程序。
tar xvf $LFS/gawk-3.1.5.tar.bz2
cd gawk-3.1.5
patch -Np1 -i $LFS/gawk-3.1.5-segfault_fix-1.patch
./configure --prefix=/usr --libexecdir=/usr/lib
cat >> config.h << "EOF"
#define HAVE_LANGINFO_CODESET 1
#define HAVE_LC_MESSAGES 1
EOF
make && make check && make install
Gettext 用于系统的国际化和本地化,可以在编译程序的时候使用本国语言支持(NLS),可以使程序的输出使用用户设置的语言而不是英文。
./configure --prefix=/usr
make && make check &&
check 要 5 个 sbu哦,有点长
Grep 可以搜索文件中符合指定匹配模式的行。tar xjvf grep-2.5.1a.tar.bz2
cd gr
cd grep-2.5.1a
patch -Np1 -i ../../sources/grep-2.5.1a-redhat_fixes-2.patch
chmod +x tests/fmbtest.sh
./configure --prefix=/usr --bindir=/bin
make
make check
make install
cd ..
rm -rf grep-2.5.1a
Groff 软件包包含几个处理和格式化文本的程序。Groff 把标准的文本和特殊的命令翻译成格式化的输出,就像你在 man 手册页里看到的那样。
tar xvf ../sources/groff-1.18.1.4.tar.gz
cd groff-1.18.1.4/
patch -Np1 -i ../../sources/groff-1.18.1.4-debian_fixes-1.patch
sed -i -e 's/2010/002D/' -e 's/2212/002D/' -e 's/2018/0060/' -e 's/2019/0027/' font/devutf8/R.proto
PAGE=A4 ./configure --prefix=/usr --enable-multibyte
make
make install
ln -sv eqn /usr/bin/geqn
ln -sv eqn /usr/bin/geqn
ln -sv tbl /usr/bin/gtbl
ls -l /usr/bin/gtbl
ls -l /usr/bin/tbl
cd ..
rm -rf groff-1.18.1.4/
gzip
tar xvf gzip-1.3.12.tar.gz
cd gzip-1.3.12
./configure --prefix=/usr --bindir=/bin
make
make check
make install
mv -v /bin/{gzexe,uncompress,zcmp,zdiff,zegrep} /usr/bin
mv -v /bin/{zfgrep,zforce,zgrep,zless,zmore,znew} /usr/bin
cd ..
rm -rf gzip-1.3.12
Inetutils 包含基本的网络程序。
patch -Np1 -i $LFS/inetutils-1.5-no_server_man_pages-2.patch
./configure --prefix=/usr --libexecdir=/usr/sbin \
--sysconfdir=/etc --localstatedir=/var \
--disable-ifconfig --disable-logger --disable-syslogd \
--disable-whois --disable-servers
make && make install
mv /usr/bin/ping /bin
iproute2
IPRoute2 包含了基本的和高级的基于 IPv4 网络的程序。
tar xvf $LFS/iproute2-2.6.20-070313.tar.bz2
cd iproute-2.6.20-070313
sed -i -e '/tc-bfifo.8/d' -e '/tc-pfifo.8/s/pbfifo/bfifo/' Makefile
make SBINDIR=/sbin
make SBINDIR=/sbin install
mv -v /sbin/arpd /usr/sbin
cd ..
rm -rf iproute-2.6.20-070313
Kbd 包含键盘映射表和键盘工具。
tar xvf ../sources/kbd-1.12.tar.bz2
cd kbd-1.12/
patch -Np1 -i ../../sources/kbd-1.12-backspace-1.patch
patch -Np1 -i ../../sources/kbd-1.12-gcc4_fixes-1.patch
./configure --datadir=/lib/kbd
make
make install
mv -v /usr/bin/{kbd_mode,openvt,setfont} /bin
cd ..
rm -rf kbd-1.12/
less
tar xvf $LFS/less-406.tar.gz
cd less-406
./configure --prefix=/usr --sysconfdir=/etc
make
make install
cd ..
rm -rf less-406
make
自动地确定一个大型程序的哪些片段需要重新编译,并且发出命令去重新编译它们。
tar cd
./configure --prefix=/usr
make && make check && make install && rm
tar xvf ../sources/man-db-2.4.4.tar.gz
cd man-db-2.4.4/
mv man/de{_DE.88591,}
mv man/es{_ES.88591,}
mv man/it{_IT.88591,}
sed -i 's,\*_\*,??,' man/Makefile.in
sed -i -e '\%\t/usr/man%d' -e '\%\t/usr/local/man%d' src/man_db.conf.in
cat >> include/manconfig.h.in << "EOF"
#define WEB_BROWSER "exec /usr/bin/lynx"
#define COL "/usr/bin/col"
#define VGRIND "/usr/bin/vgrind"
#define GRAP "/usr/bin/grap"
EOF
patch -Np1 -i ../../sources/man-db-2.4.4-fixes-1.patch
./configure --prefix=/usr --enable-mb-groff --disable-setuid
make && make install
cat >>convert-mans <<"EOF"
#!/bin/sh -e
FROM="$1"
TO="$2"
shift ; shift
while [ $# -gt 0 ]
do
FILE="$1"
shift
iconv -f "$FROM" -t "$TO" "$FILE" >.tmp.iconv
mv .tmp.iconv "$FILE"
done
EOF
install -m755 convert-mans /usr/bin
cd ..
rm -rf man-db-2.4.4
Mktemp 软件包包含用于在 shell 脚本中创建安全临时文件的程序。
tar xvf $LFS/mktemp-1.5.tar.gz
cd mktemp-1.5
patch -Np1 -i $LFS/mktemp-1.5-add_tempfile-3.patch
./configure --prefix=/usr --with-libc
make && make instal &&l make install-tempfile
cd ..
rm -rf mktemp-1.5
Module-Init-Tools 包含处理 2.5.47 及以上版本的内核模块时使用的工具。
tar xvf ../sources/module-init-tools-3.2.2.tar.bz2
cd module-init-tools-3.2.2/
patch -Np1 -i ../../sources/module-init-tools-3.2.2-modprobe-1.patch
执行下面的命令进行测试(注意 make distclean 命令需要清理源码树,因为作为测试过程的一部分,源码会重新编译
./configure
make check
make distclean
./configure --prefix=/ --enable-zlib
make
make INSTALL=install install
cd ..
rm -rf mo
Patch
根据"补丁"文件的内容来修改原来的文件。补丁文件通常是用 diff程序创建的,包含如何修改文件的指导。dule-init-tools-3.2.2/
./configure && make && make install
Psmisc 包含有用于显示进程信息的程序。
./configure --prefix=/usr --exec-prefix=""
这个确保 Psmisc 二进制文件按照 FHS 标准被安装在 /bin 而不是 /usr/bin ,因为一些 Psmisc 二进制文件将被 LFS-Bootscripts 使用。
make
这个软件包没有附带测试程序。
安装软件包:
make install
没有理由把 pstree 和 pstree.x11 程序安装在 /bin 中,所以将他们移动到 /usr/bin 中:
mv -v /bin/pstree* /usr/bin
默认情况下, Psmisc 的 pidof 程序未被安装。 这通常情况下不是问题。因为它将在这之后的 Sysvinit 包中被安装,而且这个包提供了一个更好的 pidof 程序。如果你打算不使用 Sysvinit ,则可通过创建下面的符号连接来安装完整的 Psmisc :
ln -sv killall /bin/pidof
Shadow 包含用于在安全方式下处理密码的程序。
tar xvf ../sources/shadow-4.0.18.1.tar.bz2
cd shadow-4.0.18.1/
patch -Np1 -i ../../sources/shadow-4.0.18.1-useradd_fix-2.patch
./configure --libdir=/lib --sysconfdir=/etc --enable-shared --without-selinux
sed -i 's/groups$(EXEEXT) //' src/Makefile
find man -name Makefile -exec sed -i 's/groups\.1 / /' {} \;
sed -i -e 's@#MD5_CRYPT_ENAB.no@MD5_CRYPT_ENAB yes@' -e 's@/var/spool/mail@/var/mail@' etc/login.defs
make && make install
mv -v /usr/bin/passwd /bin/
mv -v /lib/libshadow.*a /usr/lib
rm -v /lib/libshadow.so
ln -sfv ../../lib/libshadow.so.0 /usr/lib/libshadow.so
pwconv
grpconv
useradd -D -h /home/
sed -i 's/yes/no/' /etc/default/useradd
less /etc/default/useradd
passwd root (一定要设啊,要不,你就进不了你辛辛苦苦打下的‘江山’,呵呵)
Sysklogd 包含记录系统日志信息的程序,比如内核处理意外事务的日志。
cd sysklogd-1.4.1
patch -Np1 -i ../../sysklogd-1.4.1-fixes-2.patch
patch -Np1 -i ../../sysklogd-1.4.1-8bit-1.patch
make
make install
cat > /etc/syslog.conf << "EOF"
# Begin /etc/syslog.conf
auth,authpriv.* -/var/log/auth.log
*.*;auth,authpriv.none -/var/log/sys.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
*.emerg *
# End /etc/syslog.conf
EOF
Sysvinit 软件包包含一些控制系统启动、运行、关闭的程序。
cd sysvinit-2.86/
sed -i 's@Sending processes@& configured via /etc/inittab@g' src/init.c
make -C src
make -C src install
cat > /etc/inittab << "EOF"
less /etc/inittab
Tar
tar xvf $LFS/tar-1.18.tar.bz2
cd tar-1.18
./configure --prefix=/usr --bindir=/bin --libexecdir=/usr/sbin
make && make check && make install
Texinfo 软件包包含读取、写入、转换 Info 文档的程序。
cd texinfo-4.9/
patch -Np1 -i ../../sources/texinfo-4.9-multibyte-1.patch
patch -Np1 -i ../../sources/texinfo-4.9-tempfile_fix-1.patch
./configure --prefix=/usr
make
make install
make TEXMF=/usr/share/texmf install-tex
cd /usr/share/info/
rm dir
for f in *; do install-info $f dir 2>/dev/null; done
cd -
cd ..
rm -rf texinfo-4.9/
Udev 软件包包含动态地创建设备节点的程序。
tar xvf ../sources/udev-113.tar.bz2
cd udev-113/
tar xvf ../../sources/udev-config-6.3.tar.bz2
install -dv /lib/{firmware,udev/devices/{pts,shm}}
mknod -m0666 /lib/udev/devices/null c 1 3
ln -sv /proc/self/fd /lib/udev/devices/fd
ln -sv /proc/self/fd/0 /lib/udev/devices/stdin
ln -sv /proc/self/fd/1 /lib/udev/devices/stdout
ln -sv /proc/self/fd/2 /lib/udev/devices/stderr
ln -sv /proc/kcore /lib/udev/devices/core
make EXTRAS="`echo extras/*/`"
make test
make DESTDIR=/ EXTRAS="`echo extras/*/`" install
cp -v etc/udev/rules.d/[0-9]* /etc/udev/rules.d/
cd udev-config-6.3
make install
make install-doc
make install-extra-doc
cd ..
install -m644 -v docs/writing_udev_rules/index.html /usr/share/doc/udev-113/index.html
cd ..
rm -rf udev-113/
Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器,打开 tty 端口和得到内核消息。
cd util-linux-2.12r/
sed -e 's@etc/adjtime@var/lib/hwclock/adjtime@g' -i $(grep -rl '/etc/adjtime' .)
mkdir -pv /var/lib/hwclock
patch -Np1 -i ../../sources/util-linux-2.12r-cramfs-1.patch
patch -Np1 -i ../../sources/util-linux-2.12r-lseek-1.patch
./configure
make HAVE_KILL=yes HAVE_SLN=yes
make HAVE_KILL=yes HAVE_SLN=yes install
cd ..
rm -rf util-linux-2.12r/
VIM
tar xvf ../sources/vim-7.1.tar.bz2
tar xvf ../sources/vim-7.1-lang.tar.gz
cd vim71/
patch -Np1 -i ../../sources/vim-7.1-fixes-1.patch
patch -Np1 -i ../../sources/vim-7.1-mandir-1.patch
echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h
./configure --prefix=/usr --enable-multibyte
make && make install
vi
ln -sv vim /usr/bin/vi
ls -l /usr/bin/vi
ls -l /usr/bin/vim
ls -l /usr/bin/vi
vi
for L in "" fr it pl ru; do ln -sv vim.1 /usr/share/man/$L/man1/vi.1; done
ln -sv ../vim/vim71/doc /usr/share/doc/vim-7.1
cat > /etc/vimrc << "EOF"
vi /etc/vimrc
cd ..
ls
rm vim71/ -rf
logout
chroot "$LFS" /usr/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login
LFS-Bootscripts 软件包包含一套在 LFS 系统启动和关闭时的启动和停止脚本。
解压之后 安装即可
make install
时间设置
cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=1
# End /etc/sysconfig/clock
EOF
设置bash下的键盘功能键设置
cat > /etc/inputrc << "EOF"
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
"\eOH": beginning-of-line
"\eOF": end-of-line
"\e[H": beginning-of-line
"\e[F": end-of-line
EOF
设置bash 启动文件
cat > /etc/profile << "EOF"
# Begin /etc/profile
export LANG=zh_CN.UTF-8
export INPUTRC=/etc/inputrc
alias ls="ls --color"
alias ll="ls -l"
export PS1='max--> '
# End /etc/profile EOF
设置本地网络名
echo "HOSTNAME=maximilian" > /etc/sysconfig/network
设置hosts文件
cat > /etc/hosts << "EOF"
# Begin /etc/hosts (no network card version)
127.0.0.1 mylinux localhost
# End /etc/hosts (no network card version)
EOF
设置网络的静态地址
cd /etc/sysconfig/network-devices &&
mkdir -v ifconfig.eth0 &&
cat > ifconfig.eth0/ipv4 << "EOF"
ONBOOT=yes
SERVICE=ipv4-static
IP=192.168.228.200
GATEWAY=192.168.228.153
PREFIX=24
BROADCAST=192.168.228.255
EOF
cat > /etc/resolv.conf << "EOF"
#Beging /etc/resolv.conf
nameserver 192.168.228.153
EOF
建立fstab文件
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# file system mount-point type options dump fsck
# order
/dev/sdb1 / ext3 defaults 1 1
/dev/sda1 swap swap pri=1 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid=4,mode=620 0 0
shm /dev/shm tmpfs defaults 0 0
# End /etc/fstab
EOF
安装 内核 我的是 linux-2.6.22
因为我是在虚拟机下,所以,有些选项要必选,
Device Drivers->SCSI device support->SCSI low-level drivers下加入BusLogic SCSI support的支持,可以采用编译到内核来避免未用initrd脚本来加载模块而导致启动失败
支持网络则应该在Device Drivers->Networking support->Ethernet (10 or 100Mbit)加入AMD PCnet32 PCI support的支持,可以采用编译到内核也可以编译成模块的方式
文件系统 ext3 必须 加载 到内核,不要选模块哦
如果之前给内核加入了显示UTF-8编码文字的补丁的话,那么这里需要加入framebuffer的支持才能使补丁生效,在Device Drivers->Graphics support中加入Support for frame buffer devices,并选择上VESA VGA graphics supports,这里将其编译到内核中
同时还需要加入framebuffer字体支持,在Device Drivers->Graphics support->Console display driver support中加入Framebuffer Console support并选择上Select compiled-in fonts,选上VGA 8x16 font这一种字体就可以了,这里将这些选择都编译到内核中
可以保存退出了
代码:
make
make modules_install
cp -v arch/i386/boot/bzImage /boot/lfskernel-2.6.22
cp -v System.map /boot/System.map-2.6.22
cp -v .config /boot/config-2.6.22
install -d /usr/share/doc/linux-2.6.22
cp -r Documentation/* /usr/share/doc/linux-2.6.22
安装Grub,使系统能启动,这里设置需要根据情况而修改,这里以之前介绍的分区设置为例:
代码:
grub
输入root (hd1,0)
输入setup (hd1)
quit
设置grub启动菜单
代码:
cat > /boot/grub/menu.lst << "EOF"
# Begin /boot/grub/menu.lst
# By default boot the first menu entry.
default 0
# Allow 30 seconds before booting the default. timeout 30
# Use prettier colors. color green/black light-green/black
# The first entry is for LFS.
title LFS 6.3 root (hd0,1)
kernel /boot/lfskernel-2.6.22 root=/dev/sdb1
EOF
退出 哦,开始我们的自制 linux 之旅。
注意:这里root后面的磁盘分区需要根据实际情况调整。
将menu.lst连接到/etc目录下
代码:
mkdir -v /etc/grub ln -sv /boot/grub/menu.lst /etc/grub
1.重新启动计算机,并从LiveCD启动
2.加载分区
export LFS=/mnt/lfs
mkdir -pv $LFS
mount /dev/hda2 $LFS
3.加载交换分区(如果不想用交换分区或者没有交换分区可跳过此步骤)
swapon /dev/hda1
4.加载必要的文件系统
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
5.Chroot到目标系统下
chroot "$LFS" /usr/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login
6.进入编译目录
cd /sources
export LFS=/sources
如果 chroot 不能进去(有时候会报env no such file or directory等)可以手工输入如下命令:
chroot "$LFS" /usr/bin/env -i HOME=/root/ TERM="$TERM" PS1='max --->' PATH=/bin:/usr/bin:/sbin:/usr/sbin /bin/bash --login
下面贴几幅图,瞅瞅:
500)this.width=500;" border="0">
500)this.width=500;" border="0">
以上是基本的系统,也就是LFS 里的要求,要想更深入的可以学习 Blfs ALFS cLFS ,我参考了一个 Blfs ,所以装了 net-tools ,GNet-2.0.7 NcFTP-3.2.1 OpenSSH-4.7p1 Client 等软件,使其可以从其它主机登入,或者可以进入别人的SSH。见如下图所示:
500)this.width=500;" border="0">
打完收工,有什么问题,找官方文档。Google 一下,你就全知道了。我在途中遇到三四个问题,都完美的解决。呵呵
我在此参考了 官方 文档 与 耐心的人(我暂且这样称呼他吧,写的太认真了)
创建分区,并在分区上新建 必要的目录,例如tools source soft 等。
挂载
添加 lfs用户并设置其环境
.bash_profile
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
前面的步骤省略掉,可以参考官方的文档。
Binutils 是一组开发工具,包括连接器、汇编器和其他用于目标文件和档案的工具。
make -C ld clean
make -C ld LIB_PATH=/tools/lib
cp -v ld/ld-new /tools/bin
make 参数的含义:
-C ld clean
告诉 make 程序删除所有 ld 子目录中编译生成的文件。
-C ld LIB_PATH=/tools/lib
这个选项重新编译 ld 子目录中的所有文件。在命令行中指定 Makefile 的 LIB_PATH 变量值,使它明确指向临时工具目录,以覆盖默认值。这个变量的值指定了连接器的默认库搜索路径,它在这一章的稍后部分会用到。
GCC 软件包包含 GNU 编译器集合,其中有 C 和 C++ 编译器。
mkdir -v ../gcc-build
cd ../gcc-build
为编译 GCC 做准备:
../gcc-4.0.3/configure --prefix=/tools \
--with-local-prefix=/tools --disable-nls --enable-shared \
--enable-languages=c
make bootstrap
bootstrap
使用这个参数的目的不仅仅是编译 GCC ,而是重复编译它几次。它用第一次编译生成的程序来第二次编译自己,然后又用第二次编译生成的程序来第三次编译自己,最后比较第二次和第三次编译的结果,以确保编译器能毫无差错的编译自身,这通常表明编译是正确的。
make install
最后,我们创建一个必要的符号连接。因为许多程序和脚本试图运行 cc 而不是 gcc ,这样做是为了让程序能在多种 Unix 平台上运行,并保持一致性。并不是每个人都安装 GNU C 编译器。只运行 cc 而不是 gcc 可以把选择 C 编译器的自由留给系统管理员,我们这里将指向 gcc :
ln -vs gcc /tools/bin/cc
Glibc-2.5.1
代码:
tar xvf /lfs-sources/glibc-2.5.1.tar.bz2
cd glibc-2.5.1
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.5.1/configure --prefix=/tools \ --disable-profile --enable-add-ons \ --enable-kernel=2.6.0 --with-binutils=/tools/bin \ --without-gd --with-headers=/tools/include \ --without-selinux
make
mkdir -v /tools/etc
touch /tools/etc/ld.so.conf
make install
cd ..
rm -rf glibc-build
rm -rf glibc-2.5.1
测试工具安装
说明:这部分将安装3个用于第六章各种源码包编译后的测试的工具,所以如果你不打算做make check之类的事情,那么这3个包可以不装。
Tcl-8.4.15 Expect-5.43.0 DejaGNU-1.4.4
cd unix
./configure --prefix=/tools
make
make install
make install-private-headerrs
ln -sv tclsh8.4 /tools/bin/tclsh
安装 Expect
先修正一个可能导致 GCC 测试程序假失败的 bug :
patch -Np1 -i ../expect-5.43.0-spawn-1.patch
为编译 Expect 做准备:
./configure --prefix=/tools --with-tcl=/tools/lib \
--with-tclinclude=/tools/include --with-x=no
配置选项的含义:
--with-tcl=/tools/lib
这个选项确保配置脚本找到的是安装在临时工具目录下的 Tcl ,而不是宿主系统里的。
--with-tclinclude=/tools/include
这个选项告诉 Expect 到哪里寻找 Tcl 的源代码目录和头文件。使用这个选项可以避免 configure 脚本因为找不到 Tcl 的源代码目录而导致的失败。
--with-x=no
这个选项告诉 configure 脚本不要搜索 Tk(Tcl的图形界面组件)或者 X Window 系统的库,这两者都可能位于宿主系统上。
编译软件包:
make
要测试结果,请运行:make test 。请注意,已知 Expect 的测试程序会在某些不在我们控制范围内的宿主系统下出现测试失败。因此,如果您运行这里的测试程序失败了也没关系,因为这并不关键。
安装软件包:
make SCRIPTS="" install
make 参数的含义:
SCRIPTS=""
这个选项防止安装 Expect 所补充的一些并不需要的脚本。
安装 DejaGNU
为编译 DejaGNU 做准备:
./configure --prefix=/tools
编译并安装软件包:
make install
要测试结果,请运行:make check 。
gcc pass 2
cp -v gcc/Makefile.in{,.orig} &&
sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig > gcc/Makefile.in
cp -v gcc/Makefile.in{,.tmp} &&
sed 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \
> gcc/Makefile.in
patch -Np1 -i ../gcc-4.0.3-specs-1.patch
mkdir -v ../gcc-build
cd ../gcc-build
../gcc-4.0.3/configure --prefix=/tools \
--with-local-prefix=/tools --enable-clocale=gnu \
--enable-shared --enable-threads=posix \
--enable-__cxa_atexit --enable-languages=c,c++ \
--disable-libstdcxx-pch
make
make install
echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'
如果一切正常,应该不会出错,而且最后一个命令的结果应当是:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
重新安装 Binutils
再次为编译创建一个单独目录:
mkdir -v ../binutils-build
cd ../binutils-build
为编译 Binutils 做准备:
../binutils-2.16.1/configure --prefix=/tools \
--disable-nls --with-lib-path=/tools/lib
make
make install
为下一章的"再次调整工具链"阶段配置连接器:
make -C ld clean
make -C ld LIB_PATH=/usr/lib:/lib
cp -v ld/ld-new /tools/bin
Ncurses 提供独立于终端的字符终端处理库,含有功能键定义(快捷键)、屏幕绘制以及基于文本终端的图形互动功能。
./configure --prefix=/tools --with-shared \
--without-debug --without-ada --enable-overwrite
--without-ada
这个选项让 Ncurses 在即使宿主系统上安装了 Ada 编译器的情况下也不要编译其 Ada 绑定。需要这样做的原因是一旦我们进入 chroot 环境,Ada 就不能使用了。
--enable-overwrite
这个选项让 Ncurses 把它的头文件安装到 /tools/include 目录,而不是 /tools/include/ncurses 目录,以确保其它软件包可以顺利找到 Ncurses 的头文件。
make
make install
patch -Np1 -i ../bash-3.1-fixes-8.patch
为编译 Bash 做准备:
./configure --prefix=/tools --without-bash-malloc
配置选项的含义:
--without-bash-malloc
这个选项禁用了 Bash 的内存分配函数(malloc),这个函数已知会造成段错误,通过设置这个选项,Bash 将使用更为稳定的 Glibc 里的 malloc 函数。
make
make install
ln -vs bash /tools/bin/sh
安装 Bzip2
Bzip2 软件包没有 configure 脚本,用下面的命令直接编译:
make
安装软件包:
make PREFIX=/tools install
Coreutils 软件包包括一整套用于显示和设置基本系统特征的工具。
./configure --prefix=/tools
make
make install
cp -v src/su /tools/bin/su-tools
Diffutils 软件包里的程序可以向你显示两个文件或目录的差异,常用来生成软件的补丁。
./configure --prefix=/tools
make
make install
Findutils 软件包包含查找文件的工具,既能即时查找(递归的搜索目录,并可以显示、创建和维护文件),也能在数据库里查找(通常比递归查找快但是在数据库没有及时更新的情况下,结果并不可靠)。
./configure --prefix=/tools
make
make install
安装 Gawk
为编译 Gawk 做准备:
./configure --prefix=/tools
由于 configure 脚本的一个 bug ,Gawk 不能正确检测某些 Glibc 支持的 locale ,这将会导致一些问题,比如,Gettext 的测试程序会失败。修复这个 bug 的办法是在 config.h 文件结尾追加丢失的宏定义:
cat >>config.h <<"EOF"
#define HAVE_LANGINFO_CODESET 1
#define HAVE_LC_MESSAGES 1
EOF
编译软件包:
make && make installl
为编译 Grep 做准备:
./configure --prefix=/tools \
--disable-perl-regexp
配置选项的含义:
--disable-perl-regexp
这个选项确保 grep 程序不连接可能在宿主系统上存在的 PCRE(Perl 兼容正则表达式)库,因为进入 chroot 环境后,它就不能使用了。
make
make install
安装 Gzip
为编译 Gzip 做准备:
./configure --prefix=/tools
编译软件包:
make
这个软件包没有附带测试程序。
安装软件包:
make install
安装 M4
为编译 M4 做准备:
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
安装 Make
为编译 Make 做准备:
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
安装 Patch
为编译 Patch 做准备:
./configure --prefix=/tools
编译软件包:
make
这个软件包没有附带测试程序。
安装软件包:
make install
Perl 是 Practical Extraction and Report Language的缩写。Perl 将 C, sed, awk 和 sh 的最佳特性集于一身,是一种强大的编程语言。
首先应用下面的补丁,调整指向 C 库的硬连接路径:
patch -Np1 -i ../perl-5.8.8-libc-2.patch
准备编译 Perl(请正确输入下面命令中的'Data/Dumper Fcntl IO POSIX'——全是字母):
./configure.gnu --prefix=/tools -Dstatic_ext='Data/Dumper Fcntl IO POSIX'
配置选项的含义:
-Dstatic_ext='Data/Dumper Fcntl IO POSIX'
这个选项让 Perl 编译静态扩展的最小集,下一章安装和测试 Coreutils 软件包的时候需要用到。
仅需要编译这个软件包中的一小部分必要工具:
make perl utilities
尽管 Perl 附带测试程序,但我们不推荐在这里运行。由于只编译了一部分 Perl,现在运行 make test 会编译 Perl 的其余部分,而这里我们并不需要它们。如果想测试的话,可以到下一章再运行测试程序。
安装这些工具和库:
cp -v perl pod/pod2man /tools/bin
mkdir -pv /tools/lib/perl5/5.8.8
cp -Rv lib/* /tools/lib/perl5/5.8.8
sed 是一个流编辑程序,在一个输入流(从一个文件或者一个管道的输入)上进行基本的文本编辑操作。
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
Tar 软件包含有一个归档程序,用来保存文件到归档文件或者从给定的 tar 归档文件中释放文件。
./configure --prefix=/tools
make
make install
cd ..
rm -rf tar-1.18
Texinfo 软件包包含读取、写入和转换 Info 文档的程序,以提供系统文档。
./configure --prefix=/tools
make && make install
Texinfo 软件包包含读取、写入和转换 Info 文档的程序,以提供系统文档。
./configure --prefix=/tools
编译软件包:
make
要测试结果,请运行:make check 。
安装软件包:
make install
Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理驱动器,以及打开 tty 端口和处理消息。
Util-linux 默认不使用刚才安装在 /tools 目录下的头文件和库文件,我们更改配置脚本来修正这个问题:
sed -i 's@/usr/include@/tools/include@g' configure
为编译 Util-linux 做准备:
./configure
编译一些支持例程:
make -C lib
我们只需要这个软件包中的少数几个工具,因此只需要编译这几个工具就可以了:
make -C mount mount umount
make -C text-utils more
这个软件包没有附带测试程序。
把这些程序复制到临时工具目录:
cp mount/{,u}mount text-utils/more /tools/bin
清理系统 不做
6.2. 挂载虚拟内核文件系统
虚拟内核文件系统(Virtual Kernel File Systems),是指那些是由内核产生但并不存在于硬盘上(存 在于内存中)的文件系统,他们被用来与内核进行通信。
首先让我们为虚拟内核文件系统建立挂载目录:
mkdir -pv $LFS/{dev,proc,sys}
6.2.1. 创建初始设备节点
内核在引导时要求某些设备节点必须存在(特别是 console 和 null ),这些设备节点必须创建在硬盘 上才能使得内核在 udev 尚未启动之前就可以使用它们,此外还有当Linux以init=/bin/bash 启动。使用下面的命令来创建这些节点:
mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3
6.2.2.挂载并填充 /dev 目录
推荐的向 /dev 目录填充设备的方法是在 /dev 上挂载一个虚拟文件系统(比如 tmpfs),然后在设备 被检测到或被访问到的时候(通常是在系统引导的过程中)动态创建设备节点。既然现在新的系统尚未被引导, 那么就有必要通过手工挂载和填充 /dev 目录。这可以通过绑定挂载宿主系统的 /dev 目录。绑定挂载是一种 特殊的挂载方式,允许你创建一个目录或者是挂载点的镜像到其他的地方。可以使用下面的命令:
mount --bind /dev $LFS/dev
6.2.3. 挂载虚拟内核文件系统
现在挂载虚拟内核文件系统:
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
现在将要进入 chroot 环境开始编译安装最终的 LFS 系统了,注意:在这里我们只使用临时构建的工具。以 root 身份运行以下命令进入构建环境:
chroot "$LFS" /tools/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/tools/bin/bash --login +h
env 命令的参数 -i 的作用是清除所有 chroot 环境变量。后面是重新设定 HOME, TERM, PS1, PATH 等变量的值。TERM=$TERM 设定虚拟根环境中的 TERM 的值与 chroot 外面的一样。这个值是让像 vim 和 less 之类的程序可以正确操作。如果还需要重新设置其它的值,如 CFLAGS 或 CXXFLAGS ,这里是个不错的位置。
从这里开始,不再需要 LFS 环境变量了,因为所有的工作都被限制在 LFS 文件系统里面。这是由于已经告诉了 Bash shell $LFS 是现在的根目录(/)。
注意,这里 /tools/bin 位于 PATH 的最后面。也就是说当软件包的最终版本安装之后就不再使用临时工具了。为了使 shell 无法"记住"可执行二进制代码的位置,需要通过使用 +h 参数关闭 bash 的散列功能。
注意此时 bash 提示符会显示:I have no name! 这是正常的,因为 /etc/passwd 还没有创建。
现在我们在 LFS 分区中创建目录树结构,用下列命令能创建一个标准的目录树:
mkdir -pv /{bin,boot,etc/opt,home,lib,mnt,opt}
mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
for dir in /usr /usr/local; do
ln -sv share/{man,doc,info} $dir
done
mkdir -v /var/{lock,log,mail,run,spool}
mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
缺省的目录的权限模式为 755,但也并非所有的目录都如此。以上的命令有两处有所不一样:一个是 root 用户的目录,另外两个是临时文件目录。
第一个权限模式的不同之处是确保禁止任何人进入到 /root 目录中——同样的,这个模式也适用于让其它的普通用户可以工作在自己的目录中。第二个权限模式的不同之处是确保所有用户都可以写 /tmp 和 /var/tmp 目录,但不能从中删除其它用户的文件,这是由"sticky位",也就是"1777"中的"1"来设定的。
6.5.1. FHS 兼容性说明
我们的目录树是按照 FHS(Filesystem Hierarchy Standard) 标准(http://www.pathname.com/fhs/)。除了上面创建的目录外,该标准还规定了必须有 /usr/local/games 和 /usr/share/games 两个目录,但是作为一个基本系统,我们并不需要这些。如果你要完全的遵守 FHS 标准的话,就自己建立这两个目录。至于 /usr/local/share 目录下的子目录,FHS 标准规定得并不严格,所以我们就创建了(在我们看来)需要的子目录。
创建必需的文件与符号连接
一些程序使用固化的路径(hard-wired paths)指向一些目前还不存在的程序上。为了兼容这些程序,可以创建一些符号链接,然后在软件安装之后用实际文件进行替代。
ln -sv /tools/bin/{bash,cat,grep,pwd,stty} /bin
ln -sv /tools/bin/perl /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv bash /bin/sh
一个常规的Linux系统在/etc/mtab中有一个已挂载文件系统的列表。 正常情况下,这个文件在我们挂载一个新的文件系统的时候会被创建。因为我们在chroot环境下不会再挂载任何文件系统 ,所以我们需要为那些用到/etc/mtab的程序创建一个空文件:
touch /etc/mtab
为了让 root 用户可以登录而且用户名"root"可以被识别,在这里需要创建相应的 /etc/passwd 和 /etc/group 文件。
使用下面的命令创建 /etc/passwd 文件:
cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
EOF
root 的真正密码将在后面设置("x"在这里只是一个占位符)。
下面的命令创建 /etc/group 文件:
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
tape:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
EOF
这里创建的用户组并不是某个标准所要求的部分,只是因为在随后 Udev 配置将要用到而以。Linux 标准基础(LSB, Linux Standard Base, http://www.linuxbase.org) 只是推荐"root"组的 GID 为 0,另一个组"bin"的 GID 为 1 。其它所有的组名和 GID 均由系统管理员自由设定,因为比较好的软件包一般都不依赖于 GID ,而只是使用组名。
因为完整的 Glibc 在Chapter 5中已经安装,而且 /etc/passwd 和 /etc/group 文件也已创建,用户名和组名现在可以开始使用了。现在启动新的shell,驱除"I have no name!"提示符:
exec /tools/bin/bash --login +h
注意这里使用了 +h 参数。这是告诉 bash 不能使用其内部哈希表查找路径。如果没有使用这个参数,则 bash 将会记住已经执行的二进制代码的路径。为了让新编译安装的二进制代码可以马上投入使用,在这一章中,我们使用 +h 关闭了此功能。
程序 login, agetty, init (还有其它一些程序) 使用一些日志文件来记录信息,比如谁在什么时候登录了系统等等。然而如果这些日志文件不存在,这些程序则无法写入。下面初始化这些日志文件,并设置适当的权限:
touch /var/run/utmp /var/log/{btmp,lastlog,wtmp}
chgrp -v utmp /var/run/utmp /var/log/lastlog
chmod -v 664 /var/run/utmp /var/log/lastlog
/var/run/utmp 记录着现在登录的用户。/var/log/wtmp 记录所有的登录和退出。/var/log/lastlog 记录每个用户最后的登录信息。/var/log/btmp 记录错误的登录尝试
从现在开始一直到第六章的Stripping Again之前,这个阶段如果你关机或重新启动,那么重新开机后回到工作状态的步骤是:
1.重新启动计算机,并从LiveCD启动
2.加载分区
export LFS=/mnt/lfs
mkdir -pv $LFS
mount /dev/hda2 $LFS
3.加载交换分区(如果不想用交换分区或者没有交换分区可跳过此步骤)
swapon /dev/hda1
4.加载必要的文件系统
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
5.Chroot到目标系统下
chroot "$LFS" /tools/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/bin/bash --login +h
6.进入编译目录
cd /sources
export LFS=/sources
安装头文件
cp ../sources/linux-2.6.22.5.tar.bz2 ./
tar xjvf linux-2.6.22.5.tar.bz2
cd linux-2.6.22.5
sed -i '/scsi/d' include/Kbuild
make mrproper
make headers_check
make INSTALL_HDR_PATH=dest headers_install
cp -rv dest/include/* /usr/include
cd ..
rm -rf linux-2.6.22.5* -rf
安装 Man-pages
使用下述命令安装 Man-pages :
make install
在进行之前请检查一下是否glibc-2.5.1和glibc-build这两个目录已经被删除,如果没有删除请删除后在继续。
cd glibc-2.5.1
tar -xvf $LFS/glibc-libidn-2.5.1.tar.gz
mv glibc-libidn-2.5.1 libidn
sed -i '/vi_VN.TCVN/d' localedata/SUPPORTED
sed -i \
's|libs -o|libs -L/usr/lib -Wl,-dynamic-linker=/lib/ld-linux.so.2 -o|' \
scripts/test-installation.pl
sed -i 's|@BASH@|/bin/bash|' elf/ldd.bash.in
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.5.1/configure --prefix=/usr \
--disable-profile --enable-add-ons \
--enable-kernel=2.6.0 --libexecdir=/usr/lib/glibc
make
make -k check 2>&1 | tee glibc-check-log
grep Error glibc-check-log
touch /etc/ld.so.conf
make install
make localedata/install-locales将安装全部的locale,如果你不想装这么多locale的话就用localedef命令来安装,LFS手册上有例子,如果仅想加入中文的locale,就用
mkdir -pv /usr/lib/locale
localedef -i zh_CN -f GB18030 zh_CN
localedef -i zh_CN -f GBK zh_CN
localedef -i zh_CN -f UTF-8 zh_CN
localedef -i zh_CN -f GB2312 zh_CN
localedef -i zh_HK -f UTF-8 zh_CN
localedef -i zh_HK -f BIG5-HKSCS zh_CN
localedef -i zh_TW -f EUC-TW zh_CN
localedef -i zh_TW -f UTF-8 zh_CN
建立几个重要文件:
代码:
cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF
cp -v --remove-destination /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
cat > /etc/ld.so.conf << "EOF"
/usr/local/lib
/opt/lib EOF
删除编译目录
代码:
cd .. rm -rf glibc-build rm -rf glibc-2.5.1
相关知识:
glibc的测试比较容易出现错误,比如机器慢就有可能出现超时的错误,还有一些能引起错误的LFS手册上有所提及,像超时这种错误有时候很难避免,就跳过去吧。
再次调整工具链
mv -v /tools/bin/{ld,ld-old}
mv -v /tools/i686-pc-linux-gnu/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/i686-pc-linux-gnu/bin/ld
接下来,修正 GCC 的 specs 文件,使它指向新的动态链接器,这样 GCC 才能知道在哪能发现开始文件。应用一个 perl 命令:
gcc -dumpspecs | \
perl -p -e 's@/tools/lib/ld-linux.so.2@/lib/ld-linux.so.2@g;' \
-e 's@\*startfile_prefix_spec:\n@$_/usr/lib/ @g;' > \
`dirname $(gcc --print-libgcc-file-name)`/specs
修改之后,用你的眼睛亲自检查一下 specs 文件,确保已经改正确了。
重要
如果你的系统平台上,动态连接器的名字不是 ld-linux.so.2 ,你必须把上面命令里的"ld-linux.so.2"换成你的系统平台上动态连接器的名字
现在有必要停下来,检查一下新工具链的基本功能(编译和连接)是否正常,我们进行一个简单的合理性检查:
echo 'main(){}' > dummy.c
cc dummy.c -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):
[Requesting program interpreter: /lib/ld-linux.so.2]
注意,/lib 应该是动态连接器的前缀。
现在确保我们设置使用正确的开始文件:
grep -o '/usr/lib.*/crt[1in].* .*' dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded
接下来要做的是验证新的链接器是否在正确的搜索路径内:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib");
下面,确保我们是否正在使用正确的 libc:
grep "/lib/libc.so.6 " dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
attempt to open /lib/libc.so.6 succeeded
最后,确保 GCC 正在使用正确的动态链接器:
grep found dummy.log
如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):
found ld-linux.so.2 at /lib/ld-linux.so.2
如果输出与上面不同或者没有输出,那么就有大问题了。你需要检查一下前面的操作,看看问题出在哪里,并改正过来。在改正之前,不要继续后面的部份,因为没什么意义。大多数情况下,出错都是因为上面的 specs 文件没改对。当然,如果你的平台上动态连接器的名字不是 ld-linux.so.2 ,上面的结果也会不同。在继续之前要解决所有的问题。
在确定一切正常后,删除测试文件:
rm -v dummy.c a.out dummy.log
Binutils-2.17
代码:
tar xvf $LFS/binutils-2.17.tar.bz2
mkdir binutils-build
cd binutils-build
../binutils-2.17/configure --prefix=/usr --enable-shared
make tooldir=/usr
测试:
代码:
make check
这里测试统计可能会出现个别失败。
代码:
make tooldir=/usr install
cp -v ../binutils-2.17/include/libiberty.h /usr/include
cd ..
rm -rf binutils-build binutils-2.17
安装 GCC
使用一个 sed 命令来禁止 GCC 安装它自己的 libiberty.a 。我们将使用 Binutils 附带的 libiberty.a 来代替:
sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in
在节 5.4, "GCC-4.0.3 - 第一遍" 中应用的 bootstrap 编译中,编译器会有 -fomit-frame-pointer 的标志。非bootstrap编译默认是忽略这个标志的,可以应用下面的sed 命令来确保编译的可靠性。
sed -i 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in
fixincludes 脚本偶尔会因为修改系统的头文件而出错。因为GCC-4.0.3 和 Glibc-2.3.6 是不需要修改的,运行下面的命令可以避免 fixincludes 脚本运行:
sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in
GCC 中提供了一个 gccbug 脚本,会在编译时侦测 mktemp 是否存在,并且在测试中加强代码。这将会导致脚本使用一些不算很随机的名字来命名临时文件。因为我们后面会安装 mktemp ,这里我们就模仿它的存在:
sed -i 's/@have_mktemp_command@/yes/' gcc/gccbug.in
GCC 的安装指南推荐用一个新建的目录来编译它,而不是在源码目录中:
mkdir -v ../gcc-build
cd ../gcc-build
为编译 GCC 做准备:
../gcc-4.0.3/configure --prefix=/usr \
--libexecdir=/usr/lib --enable-shared \
--enable-threads=posix --enable-__cxa_atexit \
--enable-clocale=gnu --enable-languages=c,c++
编译软件包:
make
[Important]
重要
本节的GCC测试套件很重要。在任何情况下都不要省略这一步。
运行测试套件,但遇到错误不停止(你还记得那些老是出错的测试吧):
make -k check
要查看测试单元的测试结果,可以运行:
../gcc-4.0.3/contrib/test_summary
如果只想看概要,可以把输出通过管道传递给 grep -A7 Summ 。
结果可以跟 http://www.linuxfromscratch.org/lfs/build-logs/6.2/ 的进行比较。
一些预想不到的错误总是无法避免的。虽然GCC的开发者经常留意这些问题,但是有些还是没有得到解决。通常,libmudflap 测试尤其被认为是有问题的(这是一个bug,参见http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20003)。 除非测试结果给上面URL的有很多不同,一般是可以安全继续的。
安装软件包:
make install
有的软件包希望 C PreProcessor(预处理器)安装在 /lib 目录下,为了满足它们的要求,我们创建如下符号链接:
ln -sv ../usr/bin/cpp /lib
许多软件包使用 cc 作为 C 编译器的名字,为了满足它们的要求,创建如下符号链接:
ln -sv gcc /usr/bin/cc
现在,我们的最终工具链已经形成了,我们需要做的就是确保编译、链接按照我们希望的完成。我们可以通过本章前面的简册方法来实现:
echo 'main(){}' > dummy.c
cc dummy.c -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
如果所有的都工作正常,就不会有错误,并且命令的输出应该是(允许不同平台的动态链接器的名称不同):
[Requesting program interpreter: /lib/ld-linux.so.2]
现在确保我们使用正确的 startfiles:
grep -o '/usr/lib.*/crt[1in].* .*' dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是:
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.0.3/../../../crtn.o succeeded
接下来,确认新的链接器被应用到了正确的搜索路径中:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
如果所有的都工作正常,就不会有错误,并且命令的输出应该是:
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
现在,确保我们正在使用正确的 libc :
grep "/lib/libc.so.6 " dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是
attempt to open /lib/libc.so.6 succeeded
最后,确保 GCC 正在使用正确的动态链接器:
grep found dummy.log
如果所有的都工作正常,就不会有错误,并且命令的输出应该是(允许不同平台的动态链接器的名称不同):
found ld-linux.so.2 at /lib/ld-linux.so.2
如果输出不是像上面那样或者根本没有输出,那么就有大问题了。返回并检查前面的操作,找出问题,并改正过来。最有可能的原因是上面修正 specs 文件时出错。任何一个问题都需要在继续之前解决掉。
一旦工具都工作正常,清理测试文件:
rm -v dummy.c a.out dummy.log
唉,这个花费了我一个多小时的宝贵时间。总算过去了。
Berkeley DB-4.5.20
代码:
tar xvf $LFS/db-4.5.20.tar.gz
cd db-4.5.20
patch -Np1 -i $LFS/db-4.5.20-fixes-1.patch
cd build_unix
../dist/configure --prefix=/usr --enable-compat185 --enable-cxx
make
make docdir=/usr/share/doc/db-4.5.20 install
chown -Rv root:root /usr/share/doc/db-4.5.20
cd /sources
rm -rf db-4.5.20
Coreutils 软件包包括一套显示、设置基本系统属性的工具。
cd coreutils-6.9
patch -Np1 -i $LFS/coreutils-6.9-uname-1.patch
patch -Np1 -i $LFS/coreutils-6.9-suppress_uptime_kill_su-1.patch
patch -Np1 -i $LFS/coreutils-6.9-i18n-1.patch
chmod +x tests/sort/sort-mb-tests
./configure --prefix=/usr
make
make NON_ROOT_USERNAME=nobody check-root 237
echo "dummy:x:1000:nobody" >> /etc/group
echo "dummy:x:1000:1000::/root:/bin/bash" >> /etc/passwd
make NON_ROOT_USERNAME=dummy check-root
src/su dummy -c "make RUN_EXPENSIVE_TESTS=yes check"
sed -i '/dummy/d' /etc/passwd /etc/group
安装软件包:
make install
把一些程序移动到合适的位置以符合 FHS 标准:
mv -v /usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} /bin
mv -v /usr/bin/{false,hostname,ln,ls,mkdir,mknod,mv,pwd,rm} /bin
mv -v /usr/bin/{rmdir,stty,sync,true,uname} /bin
mv -v /usr/bin/chroot /usr/sbin
一些 LFS-Bootscripts 包中的脚本依赖于 head, sleep,和 nice 。由于 /usr 目录有可能在系统启动过程的早期不可用(比如尚未挂载),所以这些二进制程序需要放置在根分区上:
mv -v /usr/bin/{head,sleep,nice} /bin
Iana-Etc 软件包提供了网络服务和协议的数据。
make && make install
M4 软件包包含一个宏处理器。
./configure --prefix=/usr
make
make check && make install
Bison-2.3
tar xvf $LFS/bison-2.3.tar.bz2
cd bison-2.3
./configure --prefix=/usr
echo '#define YYENABLE_NLS 1' >> config.h make
测试
make check
这里check不会有错
make install
cd ..
rm -rf bison-2.3
Bison 软件包包括一个语法分析程序生成器。
./configure --prefix=/usr
如果 bison 程序不在 $PATH 中的话,编译时将会出现缺乏国际化支持的错误信息。下面处理可以解决这个问题:
echo '#define YYENABLE_NLS 1' >> config.h
make && make check && make install
Ncurses 程序包提供字符终端处理库,包括面板和菜单。
cd ncurses-5.6
patch -Np1 -i $LFS/ncurses-5.6-coverity_fixes-1.patch
./configure --prefix=/usr --with-shared --without-debug --enable-widec
make
make install
chmod -v 644 /usr/lib/libncurses++w.a
mv -v /usr/lib/libncursesw.so.5* /lib
ln -sfv ../../lib/libncursesw.so.5 /usr/lib/libncursesw.so
for lib in curses ncurses form panel menu ; do \
rm -vf /usr/lib/lib${lib}.so ; \
echo "INPUT(-l${lib}w)" >/usr/lib/lib${lib}.so ; \
ln -sfv lib${lib}w.a /usr/lib/lib${lib}.a ; \
done
ln -sfv libncurses++w.a /usr/lib/libncurses++.a
rm -vf /usr/lib/libcursesw.so
echo "INPUT(-lncursesw)" >/usr/lib/libcursesw.so
ln -sfv libncurses.so /usr/lib/libcurses.so
ln -sfv libncursesw.a /usr/lib/libcursesw.a
ln -sfv libncurses.a /usr/lib/libcurses.a
cd ..
rm -rf ncurses-5.6
sed 是一个流编辑器
./configure --prefix=/usr --bindir=/bin
make && make check && make install
GNU libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一的、可移植的接口中。
./configure --prefix=/usr
make && make check && make install
perl
为了运行测试套件,要先创建一个基本的 /etc/hosts 文件,好几个测试都需要它来解析 localhost 的名称:
echo "127.0.0.1 localhost $(hostname)" > /etc/hosts
对 Perl 的设置进行更多的控制,你可以运行交互的 Configure 脚本,精心选择编译配置。如果你能接受 Perl 的自动配置(这是很明智的),就用下面的命令:
./configure.gnu --prefix=/usr \
-Dman1dir=/usr/share/man/man1 \
-Dman3dir=/usr/share/man/man3 \
-Dpager="/usr/bin/less -isR"
配置选项的含义:
-Dpager="/usr/bin/less -isR"
纠正 perldoc 代码调用 less 程序时的一个错误。
-Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3
因为 Groff 还没有安装,Configure 会认为我们不想安装 Perl 的 man 手册。应用这个参数来改变这种情况:
编译软件包:
make
要测试结果,请运行:make test 。
安装软件包:
make install
readline
cd readline-5.2
clear
sed -i '/MV.*old/d' Makefile.in
sed -i '/{OLDSUFF}/c:' support/shlib-install
patch -Np1 -i ../../sources/readline-5.2-fixes-3.patch
./configure --prefix=/usr --libdir=/lib
make SHLIB_XLDFLAGS=-lncurses
make install
mv -v /lib/lib{readline,history}.a /usr/lib
rm -v /lib/lib{readline,history}.so
ln -sfv ../../lib/libreadline.so.5 /usr/lib/libreadline.so
ln -sfv ../../lib/libhistory.so.5 /usr/lib/libhistory.so
cd ..
Zlib 软件包包含 zlib 库,很多程序中的压缩或者解压缩程序都会用到这个库。
./configure --prefix=/usr --shared --libdir=/lib
399 make
400 make check
401 make install
402 mv -v /lib/libz.so ../
403 ln -sfv ../../lib/libz.so.1.2.3 /usr/lib/libz.so
404 make clean
405 ./configure --prefix=/usr
406 make
407 make check
408 make install
409 chmod -v 644 /usr/lib/libz.a
410 cd ..
411 rm -rf zlib-1.2.3
412 history
Autoconf 能生成用于自动配置源代码的 shell 脚本
./configure --prefix=/usr
make && make install
bzip
patch -Np1 -i ../../sources/bzip2-1.0.4-install_docs-1.patch
471 make -f Makefile-libbz2_so
472 make clean
473 make
474 make PREFIX=/usr install
475 cp -v bzip2-shared /bin/bzip2
476 cp -av libbz2.so* /lib
477 ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
478 rm -v /usr/bin/{bunzip2,bzcat,bzip2}
479 ln -sv bzip2 /bin/bunzip2
480 ln -sv bzip2 /bin/bzcat
481 cd ..
482 rm -rf bzip2-1.0.4
diffutils
tar xvf diffutils-2.8.1.tar.gz
486 cd diffutils-2.8.1
487 patch -Np1 -i ../../sources/diffutils-2.8.1-i18n-1.patch
488 cat man/diff.1
489 ls -l man/diff.1
490 touch man/diff.1
491 ls -l man/diff.1
492 cat man/diff.1
493 ./configure --prefix=/usr/
494 make
495 make install
496 cd ..
497 ls
498 rm -rf diffutils-2.8.1
file
./configure --prefix=/usr
make && make install
find
./configure --prefix=/usr --libexecdir=/usr/lib/findutils \
--localstatedir=/var/lib/locate
make && make check && make install
mv -v /usr/bin/find /bin
sed -i -e 's/find:=${BINDIR}/find:=\/bin/' /usr/bin/updatedb
Flex 软件包包含一个能生成识别文本模式的程序的工具。
./configure --prefix=/usr
make && make check && make install
cd flex-2.5.33
523 ./configure --prefix=/usr
524 make
525 make check
526 make install
527 ln -sv libfl.a /usr/lib/libl.a
528 ls -l /usr/lib/libl.a
529 ls -l /usr/lib/libfl.a
530 ls libfl.a -l
531 cat > /usr/bin/lex << "EOF"
#!/bin/sh
# Begin /usr/bin/lex
exec /usr/bin/flex -l "$@"
# End /usr/bin/lex
EOF
532 chmod -v 755 /usr/bin/lex
GRUB 程序包包含 GRand 统一引导装载程序。
cd grub-0.97
patch -Np1 -i $LFS/grub-0.97-disk_geometry-1.patch
./configure --prefix=/usr
make && make check
make install
mkdir -v /boot/grub
cp -v /usr/lib/grub/i386-pc/stage{1,2} /boot/grub
把 i386-pc 换成适合你的平台的路径。
i386-pc 目录还包含一些 *stage1_5 文件,是为不同的文件系统准备的。看看有哪些文件,并把你所需要的拷贝到 /boot/grub 目录下。多数人需要 e2fs_stage1_5 和/或 reiserfs_stage1_5 文件。
Gawk 软件包包含用于管理文本文件的程序。
tar xvf $LFS/gawk-3.1.5.tar.bz2
cd gawk-3.1.5
patch -Np1 -i $LFS/gawk-3.1.5-segfault_fix-1.patch
./configure --prefix=/usr --libexecdir=/usr/lib
cat >> config.h << "EOF"
#define HAVE_LANGINFO_CODESET 1
#define HAVE_LC_MESSAGES 1
EOF
make && make check && make install
Gettext 用于系统的国际化和本地化,可以在编译程序的时候使用本国语言支持(NLS),可以使程序的输出使用用户设置的语言而不是英文。
./configure --prefix=/usr
make && make check &&
check 要 5 个 sbu哦,有点长
Grep 可以搜索文件中符合指定匹配模式的行。tar xjvf grep-2.5.1a.tar.bz2
cd gr
cd grep-2.5.1a
patch -Np1 -i ../../sources/grep-2.5.1a-redhat_fixes-2.patch
chmod +x tests/fmbtest.sh
./configure --prefix=/usr --bindir=/bin
make
make check
make install
cd ..
rm -rf grep-2.5.1a
Groff 软件包包含几个处理和格式化文本的程序。Groff 把标准的文本和特殊的命令翻译成格式化的输出,就像你在 man 手册页里看到的那样。
tar xvf ../sources/groff-1.18.1.4.tar.gz
cd groff-1.18.1.4/
patch -Np1 -i ../../sources/groff-1.18.1.4-debian_fixes-1.patch
sed -i -e 's/2010/002D/' -e 's/2212/002D/' -e 's/2018/0060/' -e 's/2019/0027/' font/devutf8/R.proto
PAGE=A4 ./configure --prefix=/usr --enable-multibyte
make
make install
ln -sv eqn /usr/bin/geqn
ln -sv eqn /usr/bin/geqn
ln -sv tbl /usr/bin/gtbl
ls -l /usr/bin/gtbl
ls -l /usr/bin/tbl
cd ..
rm -rf groff-1.18.1.4/
gzip
tar xvf gzip-1.3.12.tar.gz
cd gzip-1.3.12
./configure --prefix=/usr --bindir=/bin
make
make check
make install
mv -v /bin/{gzexe,uncompress,zcmp,zdiff,zegrep} /usr/bin
mv -v /bin/{zfgrep,zforce,zgrep,zless,zmore,znew} /usr/bin
cd ..
rm -rf gzip-1.3.12
Inetutils 包含基本的网络程序。
patch -Np1 -i $LFS/inetutils-1.5-no_server_man_pages-2.patch
./configure --prefix=/usr --libexecdir=/usr/sbin \
--sysconfdir=/etc --localstatedir=/var \
--disable-ifconfig --disable-logger --disable-syslogd \
--disable-whois --disable-servers
make && make install
mv /usr/bin/ping /bin
iproute2
IPRoute2 包含了基本的和高级的基于 IPv4 网络的程序。
tar xvf $LFS/iproute2-2.6.20-070313.tar.bz2
cd iproute-2.6.20-070313
sed -i -e '/tc-bfifo.8/d' -e '/tc-pfifo.8/s/pbfifo/bfifo/' Makefile
make SBINDIR=/sbin
make SBINDIR=/sbin install
mv -v /sbin/arpd /usr/sbin
cd ..
rm -rf iproute-2.6.20-070313
Kbd 包含键盘映射表和键盘工具。
tar xvf ../sources/kbd-1.12.tar.bz2
cd kbd-1.12/
patch -Np1 -i ../../sources/kbd-1.12-backspace-1.patch
patch -Np1 -i ../../sources/kbd-1.12-gcc4_fixes-1.patch
./configure --datadir=/lib/kbd
make
make install
mv -v /usr/bin/{kbd_mode,openvt,setfont} /bin
cd ..
rm -rf kbd-1.12/
less
tar xvf $LFS/less-406.tar.gz
cd less-406
./configure --prefix=/usr --sysconfdir=/etc
make
make install
cd ..
rm -rf less-406
make
自动地确定一个大型程序的哪些片段需要重新编译,并且发出命令去重新编译它们。
tar cd
./configure --prefix=/usr
make && make check && make install && rm
tar xvf ../sources/man-db-2.4.4.tar.gz
cd man-db-2.4.4/
mv man/de{_DE.88591,}
mv man/es{_ES.88591,}
mv man/it{_IT.88591,}
sed -i 's,\*_\*,??,' man/Makefile.in
sed -i -e '\%\t/usr/man%d' -e '\%\t/usr/local/man%d' src/man_db.conf.in
cat >> include/manconfig.h.in << "EOF"
#define WEB_BROWSER "exec /usr/bin/lynx"
#define COL "/usr/bin/col"
#define VGRIND "/usr/bin/vgrind"
#define GRAP "/usr/bin/grap"
EOF
patch -Np1 -i ../../sources/man-db-2.4.4-fixes-1.patch
./configure --prefix=/usr --enable-mb-groff --disable-setuid
make && make install
cat >>convert-mans <<"EOF"
#!/bin/sh -e
FROM="$1"
TO="$2"
shift ; shift
while [ $# -gt 0 ]
do
FILE="$1"
shift
iconv -f "$FROM" -t "$TO" "$FILE" >.tmp.iconv
mv .tmp.iconv "$FILE"
done
EOF
install -m755 convert-mans /usr/bin
cd ..
rm -rf man-db-2.4.4
Mktemp 软件包包含用于在 shell 脚本中创建安全临时文件的程序。
tar xvf $LFS/mktemp-1.5.tar.gz
cd mktemp-1.5
patch -Np1 -i $LFS/mktemp-1.5-add_tempfile-3.patch
./configure --prefix=/usr --with-libc
make && make instal &&l make install-tempfile
cd ..
rm -rf mktemp-1.5
Module-Init-Tools 包含处理 2.5.47 及以上版本的内核模块时使用的工具。
tar xvf ../sources/module-init-tools-3.2.2.tar.bz2
cd module-init-tools-3.2.2/
patch -Np1 -i ../../sources/module-init-tools-3.2.2-modprobe-1.patch
执行下面的命令进行测试(注意 make distclean 命令需要清理源码树,因为作为测试过程的一部分,源码会重新编译
./configure
make check
make distclean
./configure --prefix=/ --enable-zlib
make
make INSTALL=install install
cd ..
rm -rf mo
Patch
根据"补丁"文件的内容来修改原来的文件。补丁文件通常是用 diff程序创建的,包含如何修改文件的指导。dule-init-tools-3.2.2/
./configure && make && make install
Psmisc 包含有用于显示进程信息的程序。
./configure --prefix=/usr --exec-prefix=""
这个确保 Psmisc 二进制文件按照 FHS 标准被安装在 /bin 而不是 /usr/bin ,因为一些 Psmisc 二进制文件将被 LFS-Bootscripts 使用。
make
这个软件包没有附带测试程序。
安装软件包:
make install
没有理由把 pstree 和 pstree.x11 程序安装在 /bin 中,所以将他们移动到 /usr/bin 中:
mv -v /bin/pstree* /usr/bin
默认情况下, Psmisc 的 pidof 程序未被安装。 这通常情况下不是问题。因为它将在这之后的 Sysvinit 包中被安装,而且这个包提供了一个更好的 pidof 程序。如果你打算不使用 Sysvinit ,则可通过创建下面的符号连接来安装完整的 Psmisc :
ln -sv killall /bin/pidof
Shadow 包含用于在安全方式下处理密码的程序。
tar xvf ../sources/shadow-4.0.18.1.tar.bz2
cd shadow-4.0.18.1/
patch -Np1 -i ../../sources/shadow-4.0.18.1-useradd_fix-2.patch
./configure --libdir=/lib --sysconfdir=/etc --enable-shared --without-selinux
sed -i 's/groups$(EXEEXT) //' src/Makefile
find man -name Makefile -exec sed -i 's/groups\.1 / /' {} \;
sed -i -e 's@#MD5_CRYPT_ENAB.no@MD5_CRYPT_ENAB yes@' -e 's@/var/spool/mail@/var/mail@' etc/login.defs
make && make install
mv -v /usr/bin/passwd /bin/
mv -v /lib/libshadow.*a /usr/lib
rm -v /lib/libshadow.so
ln -sfv ../../lib/libshadow.so.0 /usr/lib/libshadow.so
pwconv
grpconv
useradd -D -h /home/
sed -i 's/yes/no/' /etc/default/useradd
less /etc/default/useradd
passwd root (一定要设啊,要不,你就进不了你辛辛苦苦打下的‘江山’,呵呵)
Sysklogd 包含记录系统日志信息的程序,比如内核处理意外事务的日志。
cd sysklogd-1.4.1
patch -Np1 -i ../../sysklogd-1.4.1-fixes-2.patch
patch -Np1 -i ../../sysklogd-1.4.1-8bit-1.patch
make
make install
cat > /etc/syslog.conf << "EOF"
# Begin /etc/syslog.conf
auth,authpriv.* -/var/log/auth.log
*.*;auth,authpriv.none -/var/log/sys.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
*.emerg *
# End /etc/syslog.conf
EOF
Sysvinit 软件包包含一些控制系统启动、运行、关闭的程序。
cd sysvinit-2.86/
sed -i 's@Sending processes@& configured via /etc/inittab@g' src/init.c
make -C src
make -C src install
cat > /etc/inittab << "EOF"
less /etc/inittab
Tar
tar xvf $LFS/tar-1.18.tar.bz2
cd tar-1.18
./configure --prefix=/usr --bindir=/bin --libexecdir=/usr/sbin
make && make check && make install
Texinfo 软件包包含读取、写入、转换 Info 文档的程序。
cd texinfo-4.9/
patch -Np1 -i ../../sources/texinfo-4.9-multibyte-1.patch
patch -Np1 -i ../../sources/texinfo-4.9-tempfile_fix-1.patch
./configure --prefix=/usr
make
make install
make TEXMF=/usr/share/texmf install-tex
cd /usr/share/info/
rm dir
for f in *; do install-info $f dir 2>/dev/null; done
cd -
cd ..
rm -rf texinfo-4.9/
Udev 软件包包含动态地创建设备节点的程序。
tar xvf ../sources/udev-113.tar.bz2
cd udev-113/
tar xvf ../../sources/udev-config-6.3.tar.bz2
install -dv /lib/{firmware,udev/devices/{pts,shm}}
mknod -m0666 /lib/udev/devices/null c 1 3
ln -sv /proc/self/fd /lib/udev/devices/fd
ln -sv /proc/self/fd/0 /lib/udev/devices/stdin
ln -sv /proc/self/fd/1 /lib/udev/devices/stdout
ln -sv /proc/self/fd/2 /lib/udev/devices/stderr
ln -sv /proc/kcore /lib/udev/devices/core
make EXTRAS="`echo extras/*/`"
make test
make DESTDIR=/ EXTRAS="`echo extras/*/`" install
cp -v etc/udev/rules.d/[0-9]* /etc/udev/rules.d/
cd udev-config-6.3
make install
make install-doc
make install-extra-doc
cd ..
install -m644 -v docs/writing_udev_rules/index.html /usr/share/doc/udev-113/index.html
cd ..
rm -rf udev-113/
Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器,打开 tty 端口和得到内核消息。
cd util-linux-2.12r/
sed -e 's@etc/adjtime@var/lib/hwclock/adjtime@g' -i $(grep -rl '/etc/adjtime' .)
mkdir -pv /var/lib/hwclock
patch -Np1 -i ../../sources/util-linux-2.12r-cramfs-1.patch
patch -Np1 -i ../../sources/util-linux-2.12r-lseek-1.patch
./configure
make HAVE_KILL=yes HAVE_SLN=yes
make HAVE_KILL=yes HAVE_SLN=yes install
cd ..
rm -rf util-linux-2.12r/
VIM
tar xvf ../sources/vim-7.1.tar.bz2
tar xvf ../sources/vim-7.1-lang.tar.gz
cd vim71/
patch -Np1 -i ../../sources/vim-7.1-fixes-1.patch
patch -Np1 -i ../../sources/vim-7.1-mandir-1.patch
echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h
./configure --prefix=/usr --enable-multibyte
make && make install
vi
ln -sv vim /usr/bin/vi
ls -l /usr/bin/vi
ls -l /usr/bin/vim
ls -l /usr/bin/vi
vi
for L in "" fr it pl ru; do ln -sv vim.1 /usr/share/man/$L/man1/vi.1; done
ln -sv ../vim/vim71/doc /usr/share/doc/vim-7.1
cat > /etc/vimrc << "EOF"
vi /etc/vimrc
cd ..
ls
rm vim71/ -rf
logout
chroot "$LFS" /usr/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login
LFS-Bootscripts 软件包包含一套在 LFS 系统启动和关闭时的启动和停止脚本。
解压之后 安装即可
make install
时间设置
cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=1
# End /etc/sysconfig/clock
EOF
设置bash下的键盘功能键设置
cat > /etc/inputrc << "EOF"
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
"\eOH": beginning-of-line
"\eOF": end-of-line
"\e[H": beginning-of-line
"\e[F": end-of-line
EOF
设置bash 启动文件
cat > /etc/profile << "EOF"
# Begin /etc/profile
export LANG=zh_CN.UTF-8
export INPUTRC=/etc/inputrc
alias ls="ls --color"
alias ll="ls -l"
export PS1='max--> '
# End /etc/profile EOF
设置本地网络名
echo "HOSTNAME=maximilian" > /etc/sysconfig/network
设置hosts文件
cat > /etc/hosts << "EOF"
# Begin /etc/hosts (no network card version)
127.0.0.1 mylinux localhost
# End /etc/hosts (no network card version)
EOF
设置网络的静态地址
cd /etc/sysconfig/network-devices &&
mkdir -v ifconfig.eth0 &&
cat > ifconfig.eth0/ipv4 << "EOF"
ONBOOT=yes
SERVICE=ipv4-static
IP=192.168.228.200
GATEWAY=192.168.228.153
PREFIX=24
BROADCAST=192.168.228.255
EOF
cat > /etc/resolv.conf << "EOF"
#Beging /etc/resolv.conf
nameserver 192.168.228.153
EOF
建立fstab文件
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# file system mount-point type options dump fsck
# order
/dev/sdb1 / ext3 defaults 1 1
/dev/sda1 swap swap pri=1 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid=4,mode=620 0 0
shm /dev/shm tmpfs defaults 0 0
# End /etc/fstab
EOF
安装 内核 我的是 linux-2.6.22
因为我是在虚拟机下,所以,有些选项要必选,
Device Drivers->SCSI device support->SCSI low-level drivers下加入BusLogic SCSI support的支持,可以采用编译到内核来避免未用initrd脚本来加载模块而导致启动失败
支持网络则应该在Device Drivers->Networking support->Ethernet (10 or 100Mbit)加入AMD PCnet32 PCI support的支持,可以采用编译到内核也可以编译成模块的方式
文件系统 ext3 必须 加载 到内核,不要选模块哦
如果之前给内核加入了显示UTF-8编码文字的补丁的话,那么这里需要加入framebuffer的支持才能使补丁生效,在Device Drivers->Graphics support中加入Support for frame buffer devices,并选择上VESA VGA graphics supports,这里将其编译到内核中
同时还需要加入framebuffer字体支持,在Device Drivers->Graphics support->Console display driver support中加入Framebuffer Console support并选择上Select compiled-in fonts,选上VGA 8x16 font这一种字体就可以了,这里将这些选择都编译到内核中
可以保存退出了
代码:
make
make modules_install
cp -v arch/i386/boot/bzImage /boot/lfskernel-2.6.22
cp -v System.map /boot/System.map-2.6.22
cp -v .config /boot/config-2.6.22
install -d /usr/share/doc/linux-2.6.22
cp -r Documentation/* /usr/share/doc/linux-2.6.22
安装Grub,使系统能启动,这里设置需要根据情况而修改,这里以之前介绍的分区设置为例:
代码:
grub
输入root (hd1,0)
输入setup (hd1)
quit
设置grub启动菜单
代码:
cat > /boot/grub/menu.lst << "EOF"
# Begin /boot/grub/menu.lst
# By default boot the first menu entry.
default 0
# Allow 30 seconds before booting the default. timeout 30
# Use prettier colors. color green/black light-green/black
# The first entry is for LFS.
title LFS 6.3 root (hd0,1)
kernel /boot/lfskernel-2.6.22 root=/dev/sdb1
EOF
退出 哦,开始我们的自制 linux 之旅。
注意:这里root后面的磁盘分区需要根据实际情况调整。
将menu.lst连接到/etc目录下
代码:
mkdir -v /etc/grub ln -sv /boot/grub/menu.lst /etc/grub
1.重新启动计算机,并从LiveCD启动
2.加载分区
export LFS=/mnt/lfs
mkdir -pv $LFS
mount /dev/hda2 $LFS
3.加载交换分区(如果不想用交换分区或者没有交换分区可跳过此步骤)
swapon /dev/hda1
4.加载必要的文件系统
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts
mount -vt tmpfs shm $LFS/dev/shm
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
5.Chroot到目标系统下
chroot "$LFS" /usr/bin/env -i \
HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login
6.进入编译目录
cd /sources
export LFS=/sources
如果 chroot 不能进去(有时候会报env no such file or directory等)可以手工输入如下命令:
chroot "$LFS" /usr/bin/env -i HOME=/root/ TERM="$TERM" PS1='max --->' PATH=/bin:/usr/bin:/sbin:/usr/sbin /bin/bash --login
下面贴几幅图,瞅瞅:
500)this.width=500;" border="0">
500)this.width=500;" border="0">
以上是基本的系统,也就是LFS 里的要求,要想更深入的可以学习 Blfs ALFS cLFS ,我参考了一个 Blfs ,所以装了 net-tools ,GNet-2.0.7 NcFTP-3.2.1 OpenSSH-4.7p1 Client 等软件,使其可以从其它主机登入,或者可以进入别人的SSH。见如下图所示:
500)this.width=500;" border="0">
打完收工,有什么问题,找官方文档。Google 一下,你就全知道了。我在途中遇到三四个问题,都完美的解决。呵呵
相关阅读 更多 +