LFS 是什么?
LFS(英文 Linux From Scratch 的缩写),中文释意为“从零开始构建的 Linux”。好吧!看起来很高大上 OTZ,可它到底是什么东西呢?感觉上它好像经常和 RedHat,Debain 这类发行版混在一起,那它应该也是个发行版吧!
这样理解其实也没有什么不对,但比起发行版来,它其实更像一本书。书本只提供知识,它只教你做,不会帮你做。这才是 LFS 和别的发行版的本质区别。这本书可以教你如何亦步亦趋的从零开始搭建一个具体而微的 Linux 系统,没错,就是从零开始,是不是有一种上帝视角的感觉呢?
那么在哪儿可以找到这本“书”呢?你可以在网上找到电子版,当然,乐意的话,你可以打印出来——不过,我认为这没必要。你只需要按照这本书的指导,一个字母都不要敲错,你就能在它手把手地指导下,打磨出你自己的 Linux 系统啦!
重点是 Linux From Scratch 这个项目用户可以控制系统的所有特征,包括目录布局、脚本设置和安全设置等等。最终的系统将从源代码直接编译生成,用户可以指定在哪里安装、为什么安装以及怎样安装每一个程序。可以完全按照自己的需求定制他们的 Linux 系统,而且使用户对他们的系统有更多的控制权。
Linux From Scratch 11.0 官方文档 PDF版
本案环境:CentOS 6.6 全新最小安装。
[root@lft ~]# cat /etc/centos-release && uname -r
CentOS release 6.6 (Final)
2.6.32-504.el6.x86_64
一、环境检测:
cat > version-check.sh << "EOF"
#!/bin/bash
# Simple script to list version numbers of critical development tools
export LC_ALL=C
bash --version | head -n1 | cut -d" " -f2-4
echo "/bin/sh -> `readlink -f /bin/sh`"
echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
bison --version | head -n1
if [ -h /usr/bin/yacc ]; then
echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
elif [ -x /usr/bin/yacc ]; then
echo yacc is `/usr/bin/yacc -V | head -n1`
else
echo "yacc not found"
fi
bzip2 --version 2>&1 < /dev/null | head -n1 | cut -d" " -f1,6-
echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
diff --version | head -n1
find --version | head -n1
gawk --version | head -n1
if [ -h /usr/bin/awk ]; then
echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
elif [ -x /usr/bin/awk ]; then
echo yacc is `/usr/bin/awk --version | head -n1`
else
echo "awk not found"
fi
gcc --version | head -n1
g++ --version | head -n1
ldd --version | head -n1 | cut -d" " -f2- # glibc version
grep --version | head -n1
gzip --version | head -n1
cat /proc/version
m4 --version | head -n1
make --version | head -n1
patch --version | head -n1
echo Perl `perl -V:version`
sed --version | head -n1
tar --version | head -n1
makeinfo --version | head -n1
xz --version | head -n1
echo 'main(){}' > dummy.c && g++ -o dummy dummy.c
if [ -x dummy ]
then echo "g++ compilation OK";
else echo "g++ compilation failed"; fi
rm -f dummy.c dummy
EOF
bash version-check.sh
cat > library-check.sh << "EOF"
#!/bin/bash
for lib in lib{gmp,mpfr,mpc}.la; do
echo $lib: $(if find /usr/lib* -name $lib|
grep -q $lib;then :;else echo not;fi) found
done
unset lib
EOF
bash library-check.sh
yum install epel-release -y
yum install gcc bison binutils byacc perl patch xz texinfo gcc-c++ -y
yum install gmp-devel mpfr-devel libmpc-devel -y
1.LFS存储准备:
为LFS创建一个独立磁盘20G,这里可以按照你自己的需要的分区,这里我按照设置一个根分区和一个交换分区为例,交换分区占用1G,其余的全部分给根分区。
磁盘分区 作用
/dev/sda1 swap
/dev/sda2 作为目标系统根目录
创建及挂载目标根分区:
cfdisk /dev/sdb #使用cfdisk分区工具
mkfs -v -t ext4 /dev/sdb2 #格式化目标系统根目录
mkswap /dev/sdb1 #格式化交换分区格
blkid #查看分区情况
export LFS=/mnt/lfs #创建环境变量,$LFS来作为lfs工程的存储根目录
mkdir -pv $LFS/lfs #创建目标根目录挂载点
mount /dev/sdb2 $LFS #挂载目标根目录
创建源代码编译用目录,修改权限并下载文件
代码:
mkdir -v $LFS/sources
chmod -v a+wt $LFS/sources
cd $LFS/sources
wget ftp://mirrors-usa.go-parts.com/lfs/lfs-packages/7.7/wget-list
wget --input-file=wget-list --continue --directory-prefix=$LFS/sources
chmod a+wt是将目录或文件的属性设置为1777,这样任何人都可以对其进行读写。验证下载的文件
pushd $LFS/sources
md5sum -c md5sums
popd
mkdir -v /lfs/tools
ln -sv /lfs/tools /
ln -sv /lfs/tools执行后应该会输出
`/tools' -> `/lfs/tools'表示正确。
4.加载交换分区(如果不想用交换分区或者没有交换分区可跳过此步骤)
swapon /dev/hda1
ln -sv $LFS/tools /
6.创建lfs用户
为了避免使用权限大的账号误操作造成宿主机损失,新建一个lfs账户,加入lfs组,并且将$LFS下的src和tools两个目录属主都改为lfs
groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
passwd lfs #两次回车
chown -v lfs $LFS/tools
chown -v lfs $LFS/sources
su - lfs #切换到lfs用户环境
7.建立lfs用户的环境
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/lfs
LC_ALL=POSIX
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL PATH
EOF
source ~/.bash_profile
export命令查看输出,应该是
declare -x HOME="/home/lfs"
declare -x LC_ALL="POSIX"
declare -x LFS="/lfs"
declare -x OLDPWD
declare -x PATH="/tools/bin:/bin:/usr/bin"
declare -x PS1="\\u:\\w\\\$ "
declare -x PWD="/home/lfs"
declare -x SHLVL="1"
declare -x TERM="linux"
9.进入编译目录
cd $LFS/sources
三、开始工具链的制作
进入LFS包编译目录,基于新版本的tar包支持自动识别文件后缀,本案所有的tar包使用xvf 选择解压。
3.1 Binutils-2.25 首次编译
3.1.1 解包和编译目录创建
cd $LFS/sources
tar xvf $LFS/sources/binutils-2.25.tar.bz2
cd binutils-2.17
mkdir -v ../binutils-build
cd ../binutils-build
../binutils-2.25/configure --prefix=/tools --with-sysroot=$LFS \
--with-lib-path=/tools/lib --target=$LFS_TGT --disable-nls \
--disable-werror
这告诉配置脚本安装Binutils项目做准备 /tools目录中。
--with-sysroot=$LFS
对于交叉编译,这讲述了构建系统在$ LFS寻找目标系统所需的库。
--with-lib-path=/tools/lib
这指定库路径链接器应该配置为使用。
--target=$LFS_TGT
因为机器的描述 LFS_TGT变量比返回的值略有不同 config.guess脚本,这个开关会告诉的 配置脚本调整Binutil构建系统的交联剂。
--disable-nls
这种禁用国际化i18n是暂时不需要工具。
--disable-werror
编译器中止编译了
3.1.3 安装
make
---------- 64位系统 ----------
case $(uname -m) in
x86_64) mkdir -v /tools/lib && ln -sv lib /tools/lib64 ;;
esac
---------- 64位系统 ----------
make install
3.2 GCC-4.9.2 首次编译
3.2.1 解压GCC包,并进入解压后的文件夹,将mpfr,gmp,mpc解压到gcc-4.9.2内。
cd $LFS/sources
tar xvf sources/gcc-4.9.2.tar.bz2
cd gcc-4.9.2
tar -xf ../mpfr-3.1.2.tar.xz
mv -v mpfr-3.1.2 mpfr
tar -xf ../gmp-6.0.0a.tar.xz
mv -v gmp-6.0.0 gmp
tar -xf ../mpc-1.0.2.tar.gz
mv -v mpc-1.0.2 mpc
mkdir -v ../gcc-build
cd ../gcc-build
3.2.2 配置编译环境:
for file in \
$(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
cp -uv $file{,.orig}
sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
-e 's@/usr@/tools@g' $file.orig > $file
echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
touch $file.orig
done
3.2.3 配置编译:
sed -i '/k prot/agcc_cv_libc_provides_ssp=yes' gcc/configure
3.2.4 创建编译目录
mkdir -v ../gcc-build
cd ../gcc-build
3.2.5 编译和安装:
../gcc-4.9.2/configure --target=$LFS_TGT --prefix=/tools --with-sysroot=$LFS \
--with-newlib --without-headers --with-local-prefix=/tools \
--with-native-system-header-dir=/tools/include --disable-nls \
--disable-shared --disable-multilib --disable-decimal-float --disable-threads \
--disable-libatomic --disable-libgomp --disable-libitm --disable-libquadmath \
--disable-libsanitizer --disable-libssp --disable-libvtv --disable-libcilkrts \
--disable-libstdc++-v3 --enable-languages=c,c++
make
make install
3.3 Linux-3.19 API Headers
cd $LFS/sources
tar xvf linux-3.19
make mrproper
make INSTALL_HDR_PATH=dest headers_installcp -rv dest/include/* /tools/include
3.4 Glibc-2.21
3.4.1
cd $LFS/sources
tar xvf glibc-2.21
cd glibc-2.21
3.4.2
if [ ! -r /usr/include/rpc/types.h ]; then
su -c 'mkdir -pv /usr/include/rpc'
su -c 'cp -v sunrpc/rpc/*.h /usr/include/rpc'
fi
3.4.3
sed -e '/ia32/s/^/1:/' \
-e '/SSE2/s/^1://' \
-i sysdeps/i386/i686/multiarch/mempcpy_chk.S
3.4.4
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.21/configure \
--prefix=/tools \
--host=$LFS_TGT \
--build=$(../glibc-2.21/scripts/config.guess) \
--disable-profile \
--enable-kernel=2.6.32 \
--with-headers=/tools/include \
libc_cv_forced_unwind=yes \
libc_cv_ctors_header=yes \
libc_cv_c_cleanup=yes
make
make install
echo 'main(){}' > dummy.c
$LFS_TGT-gcc dummy.c
readelf -l a.out | grep ': /tools'
测试结果:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
rm -v dummy.c a.out
3.5 Libstdc++-4.9.2
删掉之前的GCC编译目录,重新新建GCC-build目录:
rm -rf ../gcc-build
mkdir -pv ../gcc-build
cd ../gcc-build
../gcc-4.9.2/libstdc++-v3/configure \
--host=$LFS_TGT \
--prefix=/tools \
--disable-multilib \
--disable-shared \
--disable-nls \
--disable-libstdcxx-threads \
--disable-libstdcxx-pch \
--with-gxx-include-dir=/tools/$LFS_TGT/include/c++/4.9.2
make
make install
3.6 Binutils-2.25 二次编译
rm -rf ../binutils-build
mkdir -v ../binutils-build
cd ../binutils-build
CC=$LFS_TGT-gcc \
AR=$LFS_TGT-ar \
RANLIB=$LFS_TGT-ranlib \
../binutils-2.25/configure \
--prefix=/tools \
--disable-nls \
--disable-werror \
--with-lib-path=/tools/lib \
--with-sysroot
make
make install
make -C ld clean
make -C ld LIB_PATH=/usr/lib:/lib
cp -v ld/ld-new /tools/bin
3.7 GCC-4.9.2 二次编译
3.7.1 进入gcc解压目录
cd $LFS/sources/gcc-4.9.2
3.7.2 限制文件:
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
`dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h
3.7.3 编译环境:
for file in \
$(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
cp -uv $file{,.orig}
sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
-e 's@/usr@/tools@g' $file.orig > $file
echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
touch $file.orig
done
3.7.4 加入mpfr,gmp,mpc三个包的支持
tar -xf ../mpfr-3.1.2.tar.xz
mv -v mpfr-3.1.2 mpfr
tar -xf ../gmp-6.0.0a.tar.xz
mv -v gmp-6.0.0 gmp
tar -xf ../mpc-1.0.2.tar.gz
mv -v mpc-1.0.2 mpc
3.7.5 重新创建GCC 编译目录
rm -rf ../gcc-build
mkdir -v ../gcc-build
cd ../gcc-build
3.7.6 配置编译选项,以及安装:
CC=$LFS_TGT-gcc \
CXX=$LFS_TGT-g++ \
AR=$LFS_TGT-ar \
RANLIB=$LFS_TGT-ranlib \
../gcc-4.9.2/configure \
--prefix=/tools \
--with-local-prefix=/tools \
--with-native-system-header-dir=/tools/include \
--enable-languages=c,c++ \
--disable-libstdcxx-pch \
--disable-multilib \
--disable-bootstrap \
--disable-libgomp
make
make install
3.7.8 做个软连接
ln -sv gcc /tools/bin/cc
3.7.9 测试:
echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'
测试结果
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
记得删除测试文件
rm -v dummy.c a.out
3.8 Tcl-8.6.3
编译安装并测试
cd /mnt/lfs/sources/
tar xvf tcl8.6.3-src.tar.gz
cd tcl8.6.3
./configure --prefix=/tools
make
TZ=UTC make test
根据以上信息,一共测试116项,全通过,意味可以安装
chmod -v u+w /tools/lib/libtcl8.6.so #给tcl库文件加上属主写权限
mode of `/tools/lib/libtcl8.6.so' changed to 0755 (rwxr-xr-x) #回显信息
make install-private-headers #安装tcl头文件
Installing private header files to /tools/include/ #回显信息
ln -sv tclsh8.6 /tools/bin/tclsh #制作软连接
`/tools/bin/tclsh' -> `tclsh8.6' #回显信息
3.9 Expect-5.45
cd $LFS/sources
tar xvf expect5.45.tar.gz
cd expect5.45
重写configure文件
cp -v configure{,.orig}
sed 's:/usr/local/bin:/bin:' configure.orig > configure
编译安装
./configure --prefix=/tools \
--with-tcl=/tools/lib \
--with-tclinclude=/tools/include
make
make test
测试26个文件,成功一半失败一半。官方文档说明本次测试的失败结果可以忽略。
继续安装:
make SCRIPTS="" install
3.10 DejaGNU-1.5.2
cd $LFS/sources
tar xvf dejagnu-1.5.2.tar.gz
cd dejagnu-1.5.2
./configure --prefix=/tools
make install
make check
3.11 Check-0.9.14
返回$LFS/sources 解压并安装Check
cd $LFS/sources
tar xvf check-0.9.14.tar.gz
cd check-0.9.14
编译选项
PKG_CONFIG= ./configure --prefix=/tools
make
make check
从图中可以看到7个测试全通过,继续安装即可
make install
3.12 Ncurses-5.9
没什么好说的,编译安装三部曲。
cd $LFS/sources
tar xvf ncurses-5.9.tar.gz
cd ncurses-5.9
./configure --prefix=/tools --with-shared --without-debug --without-ada --enable-widec \ --enable-overwrite
make
make install
3.13 Bash-4.3.30
编译安装后加个软链
cd $LFS/sources
tar xvf bash-4.3.30.tar.gz
cd bash-4.3.30
./configure --prefix=/tools --without-bash-malloc
make
make tests
make install
ln -sv bash /tools/bin/sh
3.14 Bzip2-1.0.6
cd $LFS/sources
tar xvf bzip2-1.0.6.tar.gz
cd bzip2-1.0.6
make
make PREFIX=/tools install
3.15 Coreutils-8.23
tar xvf coreutils-8.23.tar.xz
cd coreutils-8.23
./configure --prefix=/tools --enable-install-program=hostname
make
make RUN_EXPENSIVE_TESTS=yes check #只要测试没有失败或错误,即继续安装
make install
3.16 Diffutils-3.3
3.17 File-5.22
3.18 Findutils-4.4.2
3.19 Gawk-4.1.1
3.20 Gettext-0.19.4
tar xvf gettext-0.19.4.tar.xz
cd gettext-0.19.4
编译
cd gettext-tools
EMACS="no" ./configure --prefix=/tools --disable-shared
编译
make -C gnulib-lib
make -C intl pluralx.c
make -C src msgfmt
make -C src msgmerge
make -C src xgettext
cp -v src/{msgfmt,msgmerge,xgettext} /tools/bin
3.21 Grep-2.21
3.22 Gzip-1.6
3.23 M4-1.4.17
3.24 Patch-2.7.4
3.25 Perl-5.20.2
3.26 Sed-4.2.2
3.27 Tar-1.28
3.28 Texinfo-5.2
3.29 Util-linux-2.26
3.30 Xz-5.2.0
3.31 Stripping
工具已经安装,这一步是清理,是可有可无的,如果你打算今后还要用/tools里面的东西,那么可以strip一下来减少占用的磁盘空间,但如果做完目标系统后就删除了,不Strip也可以,反正最后也是要删掉的。
strip --strip-debug /tools/lib/*
#/usr/bin/strip --strip-unneeded /tools/{,s}bin/*
#rm -rf /tools/{,share}/{info,man,doc}
后面的步骤不再需要lfs用户权限,退出lfs用户,用root修改文件权限。
以后的操作也直接用root操作,注意时刻检查变量$LFS的值
exit
chown -R root:root $LFS/tools
至此,工具链完全制作完毕。
4.准备虚拟内核文件系统
建立系统挂载目录
export LFS=/mnt/lfs
mkdir -pv $LFS/{dev,proc,sys,run}
4.1 创建初始设备节点
mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3
4.2 挂载并填充设备目录
mount -v --bind /dev $LFS/dev
4.3 挂载虚拟内核文件系统
mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run
建立一个符号链接
if [ -h $LFS/dev/shm ]; then
mkdir -pv $LFS/$(readlink $LFS/dev/shm)
fi
4.4 进入chroot环境
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
4.5 建立必要目录、符号链接与文件
mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib/firmware,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/{color,dict,doc,info,locale,man}
mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -v /usr/libexec
mkdir -pv /usr/{,local/}share/man/man{1..8}
case $(uname -m) in
x86_64) ln -sv lib /lib64
ln -sv lib /usr/lib64
ln -sv lib /usr/local/lib64 ;;
esac
mkdir -v /var/{log,mail,spool}
ln -sv /run /var/run
ln -sv /run/lock /var/lock
mkdir -pv /var/{opt,cache,lib/{color,misc,locate},local}
4.6 建立基本文件和符号链接
ln -sv /tools/bin/{bash,cat,echo,pwd,stty} /bin
ln -sv /tools/bin/perl /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv /tools/lib/libstdc++.so{,.6} /usr/lib
sed 's/tools/usr/' /tools/lib/libstdc++.la > /usr/lib/libstdc++.la
ln -sv bash /bin/sh
ln -sv /proc/self/mounts /etc/mtab
创建用户存储文件passwd
cat > /etc/passwd << "EOF"root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
daemon:x:6:6:Daemon User:/dev/null:/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/var/run/dbus:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/falseEOF
创建用户组文件group
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty: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:
adm:x:16:
messagebus:x:18:
systemd-journal:x:23:
input:x:24:
mail:x:34:
nogroup:x:99:
users:x:999:
EOF
这时候可以把用户名位置那讨厌的“I have no name!”去掉了
exec /tools/bin/bash --login +h
用户名成功变身root
再建立一些必要的日志文件,就可以进行系统编译啦
touch /var/log/{btmp,lastlog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664 /var/log/lastlog
chmod -v 600 /var/log/btmp
以下是LFS系统的基础系统编译
4.7 Linux-3.19 API Headers
#进入linux包
cd /sources/linux-3.19
#
make mrproper
#重新编译
make INSTALL_HDR_PATH=dest headers_install
# 删除非必要文件
find dest/include \( -name .install -o -name ..install.cmd \) -deletecp -rv dest/include/* /usr/include
4.8 Man-pages-3.79
cd /sources
tar xvf man-pages-3.79.tar.xz
cd man-pages-3.79
make install
4.9 Glibc-2.21
cd /sources/glibc-2.21
patch -Np1 -i ../glibc-2.21-fhs-1.patch #打补丁
解决32位兼容问题
sed -e '/ia32/s/^/1:/' \
-e '/SSE2/s/^1://' \
-i sysdeps/i386/i686/multiarch/mempcpy_chk.S
重新创立glibc-build 目录
rm -rf ../glibc-build
mkdir -v ../glibc-build
cd ../glibc-build
../glibc-2.21/configure --prefix=/usr --disable-profile --enable-kernel=2.6.32 --enable-obsolete-rpc
make
make check
touch /etc/ld.so.conf #官方说明:为预防安装中的警告,建立一个文件
make install
为nscd建立配置文件和运行时目录
cp -v ../glibc-2.21/nscd/nscd.conf /etc/nscd.conf
mkdir -pv /var/cache/nscd
地方配置
mkdir -pv /usr/lib/locale
localedef -i cs_CZ -f UTF-8 cs_CZ.UTF-8
localedef -i de_DE -f ISO-8859-1 de_DE
localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
localedef -i de_DE -f UTF-8 de_DE.UTF-8
localedef -i en_GB -f UTF-8 en_GB.UTF-8
localedef -i en_HK -f ISO-8859-1 en_HK
localedef -i en_PH -f ISO-8859-1 en_PH
localedef -i en_US -f ISO-8859-1 en_US
localedef -i en_US -f UTF-8 en_US.UTF-8
localedef -i es_MX -f ISO-8859-1 es_MX
localedef -i fa_IR -f UTF-8 fa_IR
localedef -i fr_FR -f ISO-8859-1 fr_FR
localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro
localedef -i fr_FR -f UTF-8 fr_FR.UTF-8
localedef -i it_IT -f ISO-8859-1 it_IT
localedef -i it_IT -f UTF-8 it_IT.UTF-8
localedef -i ja_JP -f EUC-JP ja_JP
localedef -i ru_RU -f KOI8-R ru_RU.KOI8-R
localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
localedef -i zh_CN -f GB18030 zh_CN.GB18030
make localedata/install-locales
配置glic
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
安装时区数据
tar -xf ../tzdata2015a.tar.gz
ZONEINFO=/usr/share/zoneinfo
mkdir -pv $ZONEINFO/{posix,right}
for tz in etcetera southamerica northamerica europe africa antarctica \
asia australasia backward pacificnew systemv; do
zic -L /dev/null -d $ZONEINFO -y "sh yearistype.sh" ${tz}
zic -L /dev/null -d $ZONEINFO/posix -y "sh yearistype.sh" ${tz}
zic -L leapseconds -d $ZONEINFO/right -y "sh yearistype.sh" ${tz}
done
cp -v zone.tab zone1970.tab iso3166.tab $ZONEINFO
zic -d $ZONEINFO -p America/New_York
unset ZONEINFO
其中America/New_York可以改成其他地区,官方文档上是按纽约时间走的。不过没关系,时区和语言设置可以在系统运行之后再调整。
现在也可以调整,使用tzselect
然后按照提示选择:大洲->国家->时区->确认
tzselect
或者直接将地区文件复制替换/etc/localtime,比如将时间调整为上海时间
cp -v /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
配置动态加载
cat > /etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
EOF
cat >> /etc/ld.so.conf << "EOF"
# Add an include directory
include /etc/ld.so.conf.d/*.conf
EOF
mkdir -pv /etc/ld.so.conf.d
4.10 调整工具链
mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld
gcc -dumpspecs | sed -e 's@/tools@@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 | grep ': /lib'
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
grep -B1 '^ /usr/include' dummy.log
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
grep "/lib.*/libc.so.6 " dummy.log
grep found dummy.log
最后删除测试文件
rm -v dummy.c a.out dummy.log
4.11 Zlib-1.2.8
cd /sources
tar xvf zlib-1.2.8.tar.xz
./configure --prefix=/usr
make
make check
make install
mv -v /usr/lib/libz.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libz.so) /usr/lib/libz.so
4.12 File-5.22
cd ../file-5.22
./configure --prefix=/usr
make && make check
make install
4.13 Binutils-2.25
由于chroot进来,需要先进行一个环境测试
expect -c "spawn ls"
回显:
spawn ls
重建目录
rm -rf ../binutils-build/
mkdir -v ../binutils-build
cd ../binutils-build
配置编译选项
../binutils-2.25/configure --prefix=/usr --enable-shared --disable-werror
make tooldir=/usr
make -k check
make tooldir=/usr install
4.14 GMP-6.0.0a
进入目录:
cd /sources
tar xf gmp-6.0.0a.tar.xz
cd gmp-6.0.0
32位系统的加前缀:
ABI=32 ./configure ...
64位系统,无须前缀,直接继续
./configure --prefix=/usr --enable-cxx --docdir=/usr/share/doc/gmp-6.0.0a
make
make html
make check 2>&1 | tee gmp-check-log
测试,确保188个项目全部通过。用以下命令提取
awk '/tests passed/{total+=$2} ; END{print total}' gmp-check-log
安装包和文档
make install && make install-html
4.15 MPFR-3.1.2
cd /sources
tar xvf mpfr-3.1.2.tar.xz
cd mpfr-3.1.2
patch -Np1 -i ../mpfr-3.1.2-upstream_fixes-3.patch #打个补丁
./configure --prefix=/usr --enable-thread-safe --docdir=/usr/share/doc/mpfr-3.1.2
make && make html
make check
make install && make install-html
4.16 MPC-1.0.2
cd /sources
tar xvf mpc-1.0.2.tar.gz
./configure --prefix=/usr --docdir=/usr/share/doc/mpc-1.0.2
make && make html
make check
make install && make install-html
4.17 GCC-4.9.2
rm -rf ../gcc-build
mkdir -v ../gcc-build
cd ../gcc-build
重新配置
SED=sed \
../gcc-4.9.2/configure \
--prefix=/usr \
--enable-languages=c,c++ \
--disable-multilib \
--disable-bootstrap \
--with-system-zlib
make
编译完成,在测试之前需要修改堆栈限制
ulimit -s 32768
测试,测试时间会很长!!
make -k check
../gcc-4.9.2/contrib/test_summary #执行脚本查看测试结果
安装:
make install
ln -sv ../usr/bin/cpp /lib
ln -sv gcc /usr/bin/cc
install -v -dm755 /usr/lib/bfd-plugins
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/4.9.2/liblto_plugin.so /usr/lib/bfd-plugins/
测试:
echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep '/lib' #官方文档使用的是grep ': /lib'
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
grep -B4 '^ /usr/include' dummy.log
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
grep "/lib.*/libc.so.6 " dummy.log
grep found dummy.log
回显:
删除测试文件:
rm -v dummy.c a.out dummy.log
移动错位的文件:
mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib
4.18 Bzip2-1.0.6
rm -rf bzip2-1.0.6 #记得删除之前的目录!否则在下面准备编译的时候会报错
tar xvf bzip2-1.0.6
patch -Np1 -i ../bzip2-1.0.6-install_docs-1.patch #打补丁,
sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile #修正一些错误。
sed -i "s@(PREFIX)/man@(PREFIX)/share/man@g" Makefile
Bzip2准备编译:
make -f Makefile-libbz2_so #如果直接使用上次目录,会报错。
make clean
编译和安装
make && make PREFIX=/usr install
共享bzip2二进制安装到/ bin目录中,做一些必要的符号链接,和清理:
cp -v bzip2-shared /bin/bzip2
cp -av libbz2.so* /lib
ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
rm -v /usr/bin/{bunzip2,bzcat,bzip2}
ln -sv bzip2 /bin/bunzip2
ln -sv bzip2 /bin/bzcat
4.19 Pkg-config-0.28
4.20 Ncurses-5.9
4.21 Attr-2.4.47
4.22 Acl-2.2.52
4.23 Libcap-2.24
4.24 Sed-4.2.2
4.25 Shadow-4.2.1
4.26 Psmisc-22.21
4.27 Procps-ng-3.3.10
4.28 E2fsprogs-1.42.12
4.29 Coreutils-8.23
错误
GEN man/cp.1
help2man: can't get `--help' info from man/cp.td/cp
Try `--no-discard-stderr' if option outputs to stderr
Makefile:14066: recipe for target 'man/cp.1' failed
make[2]: *** [man/cp.1] Error 127
make[2]: Leaving directory '/sources/coreutils-8.23'
Makefile:11098: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/sources/coreutils-8.23'
Makefile:5765: recipe for target 'all' failed
make: *** [all] Error 2
解决方案:
开启另一个终端,
vi /mnt/lfs/sources/coreutils-8.23/Makefile
#找到行:
run_help2man = $(PERL) -- $(srcdir)/man/help2man
#将上面行修改为:
run_help2man = $(PERL) -- $(srcdir)/man/help2man --no-discard-stderr
卡壳了,处理完再继续!!
现在出现的问题是, make 之后,
make NON_ROOT_USERNAME=nobody check-root
测试无法正常结束,停止在离开目录界面, 跳过测试,强行make install,发现lib多个lib文件无法找到。 将lib文件由源lib连接到lib64后make install 可以完成,再接着mv 后, 发现后面的tar包无法再解压,无法make ,无法ls ... 大部分命令无法操作。。
请求指点!