LFS-III-构建LFS交叉工具链和临时工具

III 构建 LFS 交叉工具链和临时工具

第5节 编译交叉编译工具链

Binutils-2.37 - Pass 1

Binutils-2.37,包含汇编器、链接器以及其他用于处理目标文件的工具。

这个包很重要,因为GCC和Glibc的configure运行都会对汇编器和链接器执行各种功能测试,以确定启用或禁用哪些软件功能。

1SBU=2min1.239s

1
2
3
4
5
6
7
8
9
10
11
tar -xvf ./binutils-2.37.tar.xz 
cd binutils-2.37
mkdir -v build
cd build/
time { ../configure --prefix=$LFS/tools \
--with-sysroot=$LFS \
--target=$LFS_TGT \
--disable-nls \
--disable-werror && make && make install;}
cd ../..
rm -rf binutils-2.37

警告:
checking for -plugin option… ar: no operation specified
configure: WARNING: Failed: ar --plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so rc
no
选择无视这个警告

结论:1SBU=2min

GCC-11.2.0 - Pass 1

12SBU=19m26.439s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
tar -xvf ./gcc-11.2.0.tar.xz 
cd gcc-11.2.0
tar -xf ../mpfr-4.1.0.tar.xz
tar -xf ../gmp-6.2.1.tar.xz
tar -xf ../mpc-1.2.1.tar.gz
mv -v mpfr-4.1.0 mpfr
mv -v gmp-6.2.1 gmp
mv -v mpc-1.2.1 mpc

case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac

mkdir -v build
cd build

time { ../configure \
--target=$LFS_TGT \
--prefix=$LFS/tools \
--with-glibc-version=2.11 \
--with-sysroot=$LFS \
--with-newlib \
--without-headers \
--enable-initfini-array \
--disable-nls \
--disable-shared \
--disable-multilib \
--disable-decimal-float \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++ && make && make install;}

cd ..
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/install-tools/include/limits.h

cd ..
rm -rf gcc-11.2.0

报错:
checking for suffix of object files… configure: error: in /mnt/lfs/sources/gcc-11.2.0/build/x86_64-lfs-linux-gnu/libgcc': configure: error: cannot compute suffix of object files: cannot compile See config.log’ for more details
Makefile:13649: recipe for target ‘configure-target-libgcc’ failed
make[1]: *** [configure-target-libgcc] Error 1
make[1]: Leaving directory ‘/mnt/lfs/sources/gcc-11.2.0/build’
Makefile:946: recipe for target ‘all’ failed
make: *** [all] Error 2

检查…/configure输出,发现报错
required isl version is 0.15 or later
*** This configuration is not supported in the following subdirectories:
target-libquadmath target-libstdc+±v3 gnattools gotools target-libada target-libhsail-rt target-libphobos target-zlib target-libbacktrace target-libgfortran target-libgo target-libffi target-libobjc target-libgomp target-liboffloadmic target-libatomic target-libvtv target-libssp target-libitm target-libsanitizer
(Any other directories should still work fine.)
checking for default BUILD_CONFIG…

处理过程中发现虚拟机断网,故重启

获取isl

1
2
3
4
5
6
7
8
9
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.12.2.tar.bz2
tar jxvf isl-0.12.2.tar.bz2
cd isl-0.12.2
mkdir build
cd build
../configure
make
sudo make install -j4

配置isl过程中发现报错
checking gmp.h usability… no
checking gmp.h presence… no
checking for gmp.h… no
configure: error: gmp.h header not found

安装gmp包
wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz
发现.lz无法解压,换.xz包

1
2
3
4
5
6
7
8
9
wget https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz
tar -xvf gmp-6.2.1.tar.xz
cd gmp-6.2.1
mkdir build
cd build
../configure
make
sudo make install -j4

重启后发现/mnt/lfs下文件全部不见,重新来T_T
重复下载软件包和最后的准备工作
重新下载使用lfs执行wget,所有资源包所有者都是lfs

在glibc的检测步骤中发现不成功,因此回过头来将isl升级到0.18

1
2
3
4
5
6
7
8
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
tar -jxvf isl-0.18.tar.bz2
cd isl-0.18/
mkdir temp
cd temp
sudo ../configure --prefix=/usr/local/isl-0.18
sudo make
sudo make install

然后configure增加一个参数
--with-isl=/usr/local/isl-0.18

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
../configure \
--target=$LFS_TGT \
--prefix=$LFS/tools \
--with-glibc-version=2.11 \
--with-isl=/usr/local/isl-0.18 \
--with-sysroot=$LFS \
--with-newlib \
--without-headers \
--enable-initfini-array \
--disable-nls \
--disable-shared \
--disable-multilib \
--disable-decimal-float \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++

不行,报错,放弃这个参数

Linux-5.13.12 API Headers

0.1SBU

1
2
3
4
5
6
7
8
9
10
tar -xvf linux-5.13.12.tar.xz
cd linux-5.13.12
make mrproper
make headers
find usr/include -name '.*' -delete
rm usr/include/Makefile
cp -rv usr/include $LFS/usr
cd ..
rm -rf linux-5.13.12

glibc-2.34

4.2SBU=16.8min

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
tar -xvf glibc-2.34.tar.xz
cd glibc-2.34

case $(uname -m) in
i?86) ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3
;;
x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64
ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3
;;
esac

patch -Np1 -i ../glibc-2.34-fhs-1.patch

mkdir -v build
cd build

echo "rootsbindir=/usr/sbin" > configparms

time { ../configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(../scripts/config.guess) \
--enable-kernel=3.2 \
--with-headers=$LFS/usr/include \
libc_cv_slibdir=/usr/lib && make && make DESTDIR=$LFS install;}

sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd

//在这里检查

$LFS/tools/libexec/gcc/$LFS_TGT/11.2.0/install-tools/mkheaders

cd ../..
rm -rf glibc-2.34

报错:
x86_64-lfs-linux-gnu-gcc -shared -nostdlib -nostartfiles \
-x assembler /dev/null -o /mnt/lfs/sources/glibc-2.34/build/format.lds.so
make[1]: x86_64-lfs-linux-gnu-gcc: Command not found
Makerules:1043: recipe for target '/mnt/lfs/sources/glibc-2.34/build/format.lds' failed
make[1]: *** [/mnt/lfs/sources/glibc-2.34/build/format.lds] Error 127
make[1]: Leaving directory '/mnt/lfs/sources/glibc-2.34'
Makefile:12: recipe for target 'install' failed
make: *** [install] Error 2
解决:
放弃sudo权限
make DESTDIR=$LFS install -j4

小心
到了这里,必须停下来确认新工具链的基本功能(编译和链接)都是像预期的那样正常工作。运行下面的命令进行全面的检查:

1
2
3
4
5
echo 'int main(){}' > dummy.c
$LFS_TGT-gcc dummy.c
readelf -l a.out | grep '/ld-linux'
rm -v dummy.c a.out

如果一切工作正常的话,这里应该没有错误,最后一个命令的输出形式会是:

1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

注意 32 位机器上对应的解释器名字是 /tools/lib/ld-linux.so.2。

如果输出不是像上面那样或者根本就没有输出,那么可能某些地方出错了。调查并回溯这些步骤,找出问题所在并改正它。在继续之前必须解决这个问题。

一旦一切都顺利,清理测试文件:

1
2
rm -v dummy.c a.out

Libstdc++ from GCC-11.2.0 - Pass 1

0.4SBU=0.8min

c++源码在gcc里面,因此要重新解压gcc包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
tar -xvf ./gcc-11.2.0.tar.xz 
cd gcc-11.2.0

mkdir -v build
cd build

time { ../libstdc++-v3/configure \
--host=$LFS_TGT \
--build=$(../config.guess) \
--prefix=/usr \
--disable-multilib \
--disable-nls \
--disable-libstdcxx-pch \
--with-gxx-include-dir=/tools/$LFS_TGT/include/c++/11.2.0 && make && make DESTDIR=$LFS install;}

cd ../..
rm -rf gcc-11.2.0

报错,无法安装
libtool: install: x86_64-lfs-linux-gnu-ranlib /mnt/lfs/usr/lib/../lib/libsupc++.a
../libtool: line 1132: x86_64-lfs-linux-gnu-ranlib: command not found
Makefile:707: recipe for target 'install-toolexeclibLTLIBRARIES' failed
make[2]: *** [install-toolexeclibLTLIBRARIES] Error 127
make[2]: Leaving directory '/mnt/lfs/sources/gcc-11.2.0/build/libsupc++'
Makefile:841: recipe for target 'install-am' failed
make[1]: *** [install-am] Error 2
make[1]: Leaving directory '/mnt/lfs/sources/gcc-11.2.0/build/libsupc++'
Makefile:568: recipe for target 'install-recursive' failed
make: *** [install-recursive] Error 1

检查配置../libstdc++-v3/configure,发现警告
configure: WARNING: === You have requested GNU symbol versioning, but
configure: WARNING: === you are not building a shared libgcc_s.
configure: WARNING: === Symbol versioning will be disabled.
报错
Makefile:1765: recipe for target 'x86_64-lfs-linux-gnu/bits/largefile-config.h' failed
make: [x86_64-lfs-linux-gnu/bits/largefile-config.h] Error 1 (ignored)
Makefile:1765: recipe for target 'x86_64-lfs-linux-gnu/bits/largefile-config.h' failed
make: [x86_64-lfs-linux-gnu/bits/largefile-config.h] Error 1 (ignored)

检查configure
configure: target-libgomp not built

做到这里时,发现重启后没有mount /dev/sda3,没有挂载硬盘,导致卷土重来。

做到检查那一步时,失败,同样卷土重来。

1
2
3
4
5
6
7
8
9
10
11
/mnt/lfs/tools/lib/gcc/x86_64-lfs-linux-gnu/11.2.0/../../../../x86_64-lfs-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
../Rules:222: recipe for target '/mnt/lfs/sources/glibc-2.34/build/support/links-dso-program' failed
make[2]: *** [/mnt/lfs/sources/glibc-2.34/build/support/links-dso-program] Error 1
make[2]: Leaving directory '/mnt/lfs/sources/glibc-2.34/support'
Makefile:478: recipe for target 'support/others' failed
make[1]: *** [support/others] Error 2
make[1]: Leaving directory '/mnt/lfs/sources/glibc-2.34'
Makefile:9: recipe for target 'all' failed
make: *** [all] Error 2

重启后回复工作状态 #1

从现在开始一直到临时系统制作结束,也就是完成Stripping中间的步骤中如果重新启动的恢复步骤:

1
2
su
mount /dev/sda* $LFS

第6章 交叉编译临时工具

m4-1.4.19

1
2
3
4
5
6
7
8
9
tar -xvf m4-1.4.19.tar.xz
cd m4-1.4.19

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf m4-1.4.19

出错解决

m4&coreutils&Gzip&sed&tar:

In file included from /mnt/lfs/usr/include/stdlib.h:1024,
from ./stdlib.h:36,
from chdir-long.c:25:
/mnt/lfs/usr/include/bits/stdlib.h: In function ‘wctomb’:
/mnt/lfs/usr/include/bits/stdlib.h:94:3: error: #error “Assumed value of MB_LEN_MAX wrong”
94 | # error “Assumed value of MB_LEN_MAX wrong”
| ^~~~~
Makefile:1866: recipe for target ‘chdir-long.o’ failed
make[3]: *** [chdir-long.o] Error 1
make[3]: Leaving directory ‘/mnt/lfs/sources/gzip-1.10/lib’
Makefile:1667: recipe for target ‘all’ failed
make[2]: *** [all] Error 2
make[2]: Leaving directory ‘/mnt/lfs/sources/gzip-1.10/lib’
Makefile:1768: recipe for target ‘all-recursive’ failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory ‘/mnt/lfs/sources/gzip-1.10’
Makefile:1549: recipe for target ‘all’ failed
make: *** [all] Error 2

解决:在gcc解压包中的gcc文件夹中找到glimits.h,将MB_MAX_LENGTH由1改为16

diffutils&grep&patch:

stackvma.c: In function ‘rof_open’:
stackvma.c:122:30: error: ‘PATH_MAX’ undeclared (first use in this function)
122 | # define MIN_LEFTOVER (73 + PATH_MAX)
| ^~~~~~~~
stackvma.c:172:18: note: in expansion of macro ‘MIN_LEFTOVER’
172 | if (size > MIN_LEFTOVER)
| ^~~~~~~~~~~~
stackvma.c:122:30: note: each undeclared identifier is reported only once for each function it appears in
122 | # define MIN_LEFTOVER (73 + PATH_MAX)
| ^~~~~~~~
stackvma.c:172:18: note: in expansion of macro ‘MIN_LEFTOVER’
172 | if (size > MIN_LEFTOVER)
| ^~~~~~~~~~~~
Makefile:2319: recipe for target ‘stackvma.o’ failed
make[2]: *** [stackvma.o] Error 1
make[2]: Leaving directory ‘/mnt/lfs/sources/diffutils-3.8/lib’
Makefile:2019: recipe for target ‘all’ failed
make[1]: *** [all] Error 2
make[1]: Leaving directory ‘/mnt/lfs/sources/diffutils-3.8/lib’
Makefile:1650: recipe for target ‘all-recursive’ failed
make: *** [all-recursive] Error 1

解决:在出错的源文件中加入#include <linux/limits.h>

findutils:

buildcmd.c: In function ‘bc_init_controlinfo’:
buildcmd.c:491:29: error: ‘_POSIX_ARG_MAX’ undeclared (first use in this function); did you mean ‘_SC_ARG_MAX’?
491 | ctl->posix_arg_size_min = _POSIX_ARG_MAX;
| ^~~~~~~~~~~~~~
| _SC_ARG_MAX
buildcmd.c:491:29: note: each undeclared identifier is reported only once for each function it appears in
Makefile:2296: recipe for target ‘buildcmd.o’ failed
make[2]: *** [buildcmd.o] Error 1
make[2]: Leaving directory ‘/mnt/lfs/sources/findutils-4.8.0/lib’
Makefile:2357: recipe for target ‘all-recursive’ failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory ‘/mnt/lfs/sources/findutils-4.8.0’
Makefile:2296: recipe for target ‘all’ failed
make: *** [all] Error 2

解决:在出错的源文件中加入#include <bits/posix1_lim.h>

Ncurses-6.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
tar -xvf ncurses-6.2.tar.gz
cd ncurses-6.2

sed -i s/mawk// configure

mkdir build
pushd build
../configure
make -C include
make -C progs tic
popd

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(./config.guess) \
--mandir=/usr/share/man \
--with-manpage-format=normal \
--with-shared \
--without-debug \
--without-ada \
--without-normal \
--enable-widec && make && make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install;}

echo "INPUT(-lncursesw)" > $LFS/usr/lib/libncurses.so

cd ..
rm -rf ncurses-6.2

Bash-5.1.8

1
2
3
4
5
6
7
8
9
10
11
12
13
tar -xvf bash-5.1.8.tar.gz
cd bash-5.1.8

time { ./configure --prefix=/usr \
--build=$(support/config.guess) \
--host=$LFS_TGT \
--without-bash-malloc && make && make DESTDIR=$LFS install;}

ln -sv bash $LFS/bin/sh

cd ..
rm -rf bash-5.1.8

coreutils-8.32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
tar -xvf coreutils-8.32.tar.xz
cd coreutils-8.32

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--enable-install-program=hostname \
--enable-no-install-program=kill,uptime && make && make DESTDIR=$LFS install;}

mv -v $LFS/usr/bin/chroot $LFS/usr/sbin
mkdir -pv $LFS/usr/share/man/man8
mv -v $LFS/usr/share/man/man1/chroot.1 $LFS/usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/' $LFS/usr/share/man/man8/chroot.8

cd ..
rm -rf coreutils-8.32

diffutils-3.8

1
2
3
4
5
6
7
8
tar -xvf diffutils-3.8.tar.xz
cd diffutils-3.8

time { ./configure --prefix=/usr --host=$LFS_TGT && make && make DESTDIR=$LFS install;}

cd ..
rm -rf diffutils-3.8

File-5.40

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
tar -xvf file-5.40.tar.gz 

cd file-5.40

mkdir build
pushd build
../configure --disable-bzlib \
--disable-libseccomp \
--disable-xzlib \
--disable-zlib
make
popd

time { ./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess) && make FILE_COMPILE=$(pwd)/build/src/file && make DESTDIR=$LFS install;}

cd ..
rm -rf file-5.40

Findutils-4.8.0

1
2
3
4
5
6
7
8
9
10
11
tar -xvf findutils-4.8.0.tar.xz
cd findutils-4.8.0

time { ./configure --prefix=/usr \
--localstatedir=/var/lib/locate \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf findutils-4.8.0

gawk-5.1.0

1
2
3
4
5
6
7
8
9
10
11
12
tar -xvf gawk-5.1.0.tar.xz
cd gawk-5.1.0

sed -i 's/extras//' Makefile.in

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(./config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf gawk-5.1.0

grep-3.7

1
2
3
4
5
6
7
8
9
tar -xvf grep-3.7.tar.xz
cd grep-3.7

time { ./configure --prefix=/usr \
--host=$LFS_TGT && make && make DESTDIR=$LFS install;}

cd ..
rm -rf grep-3.7

gzip-1.10

1
2
3
4
5
6
7
8
9
tar -xvf gzip-1.10.tar.xz
cd gzip-1.10

time { ./configure --prefix=/usr \
--host=$LFS_TGT && make && make DESTDIR=$LFS install;}

cd ..
rm -rf gzip-1.10

Make-4.3

1
2
3
4
5
6
7
8
9
10
11
tar -xvf make-4.3.tar.gz
cd make-4.3

time { ./configure --prefix=/usr \
--without-guile \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf make-4.3

Patch-2.7.6

1
2
3
4
5
6
7
8
9
10
tar -xvf patch-2.7.6.tar.xz
cd patch-2.7.6

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf patch-2.7.6

Sed-4.8

1
2
3
4
5
6
7
8
9
tar -xvf sed-4.8.tar.xz
cd sed-4.8

time { ./configure --prefix=/usr \
--host=$LFS_TGT && make && make DESTDIR=$LFS install;}

cd ..
rm -rf sed-4.8

tar-1.34

1
2
3
4
5
6
7
8
9
10
tar -xvf tar-1.34.tar.xz
cd tar-1.34

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) && make && make DESTDIR=$LFS install;}

cd ..
rm -rf tar-1.34

xz-5.2.5

1
2
3
4
5
6
7
8
9
10
11
12
tar -xvf xz-5.2.5.tar.xz
cd xz-5.2.5

time { ./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--disable-static \
--docdir=/usr/share/doc/xz-5.2.5 && make && make DESTDIR=$LFS install;}

cd ..
rm -rf xz-5.2.5

binutils-2.37 pass 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tar -xvf ./binutils-2.37.tar.xz 
cd binutils-2.37
mkdir -v build
cd build/

time { ../configure \
--prefix=/usr \
--build=$(../config.guess) \
--host=$LFS_TGT \
--disable-nls \
--enable-shared \
--disable-werror \
--enable-64-bit-bfd && make && make DESTDIR=$LFS install -j1;}

install -vm755 libctf/.libs/libctf.so.0.0.0 $LFS/usr/lib

cd ../..
rm -rf binutils-2.37

GCC-11.2.0 pass 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
tar -xvf ./gcc-11.2.0.tar.xz 
cd gcc-11.2.0
tar -xf ../mpfr-4.1.0.tar.xz
tar -xf ../gmp-6.2.1.tar.xz
tar -xf ../mpc-1.2.1.tar.gz
mv -v mpfr-4.1.0 mpfr
mv -v gmp-6.2.1 gmp
mv -v mpc-1.2.1 mpc

case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' -i.orig gcc/config/i386/t-linux64
;;
esac

mkdir -v build
cd build/

mkdir -pv $LFS_TGT/libgcc
ln -s ../../../libgcc/gthr-posix.h $LFS_TGT/libgcc/gthr-default.h

time { ../configure \
--build=$(../config.guess) \
--host=$LFS_TGT \
--prefix=/usr \
CC_FOR_TARGET=$LFS_TGT-gcc \
--with-build-sysroot=$LFS \
--enable-initfini-array \
--disable-nls \
--disable-multilib \
--disable-decimal-float \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++ && make && make DESTDIR=$LFS install;}

ln -sv gcc $LFS/usr/bin/cc

cd ../..
rm -rf gcc-11.2.0

!!!在这里备份!!!

第7章 改变文件属主并构建其他临时工具

chroot

进入root

1
su

准备虚拟内核

概述
首先,安装一些软件包的构建机制所必须的工具。这样就解决了所有的循环依赖问题,可以使用 chroot 环境进行构建,它与宿主系统除正在运行的内核外完全隔离。

为了隔离环境的正常工作,必须它与正在运行的内核之间建立一些通信机制。通过所谓的虚拟内核文件系统达成这一目的,它们必须在进入 chroot 环境时挂载。

从现在开始,所有命令必须以 root 用户身份执行,且 LFS 变量必须正确设定。 在进入 chroot 之后,仍然以 root 身份执行所有命令!

改变所有者

目前,$LFS 中整个目录树的所有者都是 lfs,这个用户只在宿主系统存在。

如果不改变 $LFS 中文件和目录的所有权,它们会被一个没有对应账户的用户 ID 所有。这是危险的,因为后续创建的新用户可能获得这个用户 ID,并成为 $LFS 中全部文件的所有者,从而产生恶意操作这些文件的可能。

为了避免这样的问题,执行以下命令,将 $LFS/* 目录的所有者改变为 root:

准备虚拟内核文件系统

内核对外提供了一些文件系统,以便自己和用户空间进行通信。它们是虚拟文件系统,并不占用磁盘空间,其内容保留在内存中。

首先创建这些文件系统的挂载点:

创建初始设备节点

在内核引导系统时,它需要一些设备节点,特别是 console 和 null 两个设备。它们需要创建在硬盘上,这样在内核填充 /dev 前,或者 Linux 使用 init=/bin/bash 内核选项启动时,也能使用它们。

运行以下命令创建它们:

挂载和填充 /dev
用设备文件填充 /dev 目录的推荐方法是挂载一个虚拟文件系统 (例如 tmpfs) 到 /dev,然后在设备被发现或访问时动态地创建设备文件。

这个工作通常由 Udev 在系统引导时完成。然而,我们的新系统还没有 Udev,也没有被引导过,因此必须手工挂载和填充 /dev。这可以通过绑定挂载宿主系统的 /dev 目录就实现。绑定挂载是一种特殊挂载类型,它允许在另外的位置创建某个目录或挂载点的映像。

运行以下命令进行绑定挂载:

挂载虚拟内核文件系统

现在挂载其余的虚拟内核文件系统:

在某些宿主系统上,/dev/shm 是一个指向 /run/shm 的符号链接。我们已经在 /run 下挂载了 tmpfs 文件系统,因此在这里只需要创建一个目录。

chroot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
chown -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools}
case $(uname -m) in
x86_64) chown -R root:root $LFS/lib64 ;;
esac

mkdir -pv $LFS/{dev,proc,sys,run}

mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3

mount -v --bind /dev $LFS/dev

mount -v --bind /dev/pts $LFS/dev/pts
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

chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
/bin/bash --login +h

mkdir -pv /{boot,home,mnt,opt,srv}

mkdir -pv /etc/{opt,sysconfig}
mkdir -pv /lib/firmware
mkdir -pv /media/{floppy,cdrom}
mkdir -pv /usr/{,local/}{include,src}
mkdir -pv /usr/local/{bin,lib,sbin}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir -pv /var/{cache,local,log,mail,opt,spool}
mkdir -pv /var/lib/{color,misc,locate}
ln -sfv /run /var/run
ln -sfv /run/lock /var/lock
install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp

ln -sv /proc/self/mounts /etc/mtab

cat > /etc/hosts << EOF
127.0.0.1 localhost $(hostname)
::1 localhost
EOF

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:/run/dbus:/bin/false
uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
EOF

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:
input:x:24:
mail:x:34:
kvm:x:61:
uuidd:x:80:
wheel:x:97:
nogroup:x:99:
users:x:999:
EOF

echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd
echo "tester:x:101:" >> /etc/group
install -o tester -d /home/tester

exec /bin/bash --login +h

touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664 /var/log/lastlog
chmod -v 600 /var/log/btmp

执行,报错

1
2
3
4
5
6
7
8
9
10
11
12
Command 'chroot' is available in '/usr/sbin/chroot'
The command could not be located because '/usr/sbin' is not included in the PATH environment variable.
This is most likely caused by the lack of administrative privileges associated with your user account.
chroot: command not found

查看$PATH
echo $PATH
/mnt/lfs/tools/bin:/bin:/usr/bin

将/usr/sbin加入$PATH


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(lfs chroot) root:/sources/gcc-11.2.0/build# ../libstdc++-v3/configure \
CXXFLAGS="-g -O2 -D_GNU_SOURCE" \
--prefix=/usr \
--disable-multilib \
--disable-nls \
--host=$(uname -m)-lfs-linux-gnu \
--disable-libstdcxx-pch
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-lfs-linux-gnu
checking target system type... x86_64-lfs-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for x86_64-lfs-linux-gnu-strip... no
checking for strip... strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for x86_64-lfs-linux-gnu-gcc... no
checking for gcc... no
checking for x86_64-lfs-linux-gnu-cc... no
checking for cc... no
checking for x86_64-lfs-linux-gnu-cl.exe... no
checking for cl.exe... no
configure: error: in `/sources/gcc-11.2.0/build':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

解决:将/tools/bin加入PATH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(lfs chroot) root:/sources/gcc-11.2.0/build# ../libstdc++-v3/configure \
CXXFLAGS="-g -O2 -D_GNU_SOURCE" \
--prefix=/usr \
--disable-multilib \
--disable-nls \
--host=$(uname -m)-lfs-linux-gnu \
--disable-libstdcxx-pch
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-lfs-linux-gnu
checking target system type... x86_64-lfs-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for x86_64-lfs-linux-gnu-strip... x86_64-lfs-linux-gnu-strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for x86_64-lfs-linux-gnu-gcc... x86_64-lfs-linux-gnu-gcc
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether x86_64-lfs-linux-gnu-gcc accepts -g... yes
checking for x86_64-lfs-linux-gnu-gcc option to accept ISO C89... unsupported
checking whether x86_64-lfs-linux-gnu-gcc understands -c and -o together... yes
checking for x86_64-lfs-linux-gnu-g++... x86_64-lfs-linux-gnu-g++
checking whether we are using the GNU C++ compiler... yes
checking whether x86_64-lfs-linux-gnu-g++ accepts -g... yes
checking for special C compiler options needed for large files... no
checking for _FILE_OFFSET_BITS value needed for large files... unknown
checking for _LARGE_FILES value needed for large files... unknown
checking how to run the C preprocessor... /lib/cpp
configure: error: in `/sources/gcc-11.2.0/build':
configure: error: C preprocessor "/lib/cpp" fails sanity check
See `config.log' for more details

重启后恢复工作状态 #2

这个时候如果你关机或重新启动,那么重新开机后回到工作状态的步骤是:

1
su
1
2
3
4
5
6
7
8
9
10
11
12
13
mount -v --bind /dev $LFS/dev

mount -v --bind /dev/pts $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run

chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
/bin/bash --login +h

Libstdc++ form GCC-11.2.0 pass 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tar -xvf gcc-11.2.0.tar.xz
cd gcc-11.2.0

ln -s gthr-posix.h libgcc/gthr-default.h

mkdir -v build
cd build

time { ../libstdc++-v3/configure \
CXXFLAGS="-g -O2 -D_GNU_SOURCE" \
--prefix=/usr \
--disable-multilib \
--disable-nls \
--host=$(uname -m)-lfs-linux-gnu \
--disable-libstdcxx-pch && make && make install;}

cd ../..
rm -rf gcc-11.2.0

Gettext-0.21

1
2
3
4
5
6
7
8
9
tar -xvf gettext-0.21.tar.xz
cd gettext-0.21

time { ./configure --disable-shared && make;}

cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin

cd ..rm -rf gettext-0.21

Bison-3.7.6

1
2
3
4
5
6
7
8
9
tar -xvf bison-3.7.6.tar.xz
cd bison-3.7.6

time { ./configure --prefix=/usr \
--docdir=/usr/share/doc/bison-3.7.6 && make && make install;}

cd ..
rm -rf bison-3.7.6

Perl-5.34.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tar -xvf perl-5.34.0.tar.xz
cd perl-5.34.0

time { sh Configure -des \
-Dprefix=/usr \
-Dvendorprefix=/usr \
-Dprivlib=/usr/lib/perl5/5.34/core_perl \
-Darchlib=/usr/lib/perl5/5.34/core_perl \
-Dsitelib=/usr/lib/perl5/5.34/site_perl \
-Dsitearch=/usr/lib/perl5/5.34/site_perl \
-Dvendorlib=/usr/lib/perl5/5.34/vendor_perl \
-Dvendorarch=/usr/lib/perl5/5.34/vendor_perl && make && make install;}

cd ..
rm -rf perl-5.34.0

编译安装失败,运行make test,发现以下报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
sh Configure -des \
-Dprefix=/usr \
-Dvendorprefix=/usr \
-Dprivlib=/usr/lib/perl5/5.34/core_perl \
-Darchlib=/usr/lib/perl5/5.34/core_perl \
-Dsitelib=/usr/lib/perl5/5.34/site_perl \
-Dsitearch=/usr/lib/perl5/5.34/site_perl \
-Dvendorlib=/usr/lib/perl5/5.34/vendor_perl \
-Dvendorarch=/usr/lib/perl5/5.34/vendor_perl

make
make install


Failed 6 tests out of 2437, 99.75% okay.
../cpan/Socket/t/getnameinfo.t
../dist/Net-Ping/t/110_icmp_inst.t
../dist/Net-Ping/t/500_ping_icmp.t
../dist/Net-Ping/t/501_ping_icmpv6.t
../dist/Net-Ping/t/520_icmp_ttl.t
../lib/Net/hostent.t

cpan/Socket/t/getnameinfo ........................................ # Failed test '$err == 0 for {family=AF_INET,port=80,sinaddr=127.0.0.1}/NI_NUMERICSERV'
# at t/getnameinfo.t line 26.
# got: -3
# expected: 0
# Failed test '$host is nonzero length for NS'
# at t/getnameinfo.t line 30.
# Looks like you failed 2 tests of 13.
FAILED at test 9

dist/Net-Ping/t/520_icmp_ttl ..................................... Can't get icmp protocol by name at t/520_icmp_ttl.t line 23.
# Looks like your test exited with 2 just after 1.
FAILED--non-zero wait status: 512

dist/Net-Ping/t/501_ping_icmpv6 .................................. Can't get ipv6-icmp protocol by name at t/501_ping_icmpv6.t line 49.
FAILED--no leader found

dist/Net-Ping/t/500_ping_icmp .................................... Can't get icmp protocol by name at t/500_ping_icmp.t line 58.
FAILED--no leader found

dist/Net-Ping/t/110_icmp_inst .................................... Can't get icmp protocol by name at t/110_icmp_inst.t line 24.
# Looks like your test exited with 2 just after 1.
FAILED--expected 2 tests, saw 1

lib/Net/hostent .................................................. # Failed test 'gethostbyaddr('127.0.0.1')'
# at ../lib/Net/hostent.t line 46.
# Looks like your test exited with 1 just after 4.
FAILED at test 4

以及一个ok的提示
t/op/magic ....................................................... Can't exec "ps": No such file or directory at op/magic.t line 830.
ok

### Since not all tests were successful, you may want to run some of
### them individually and examine any diagnostic messages they produce.
### See the INSTALL document's section on "make test".
### You have a good chance to get more information by running
### ./perl harness
### in the 't' directory since most (>=80%) of the tests succeeded.
### You may have to set your dynamic library search path,
### LD_LIBRARY_PATH, to point to the build directory:
### setenv LD_LIBRARY_PATH `pwd`; cd t; ./perl harness
### LD_LIBRARY_PATH=`pwd`; export LD_LIBRARY_PATH; cd t; ./perl harness
### export LD_LIBRARY_PATH=`pwd`; cd t; ./perl harness
### for csh-style shells, like tcsh; or for traditional/modern
### Bourne-style shells, like bash, ksh, and zsh, respectively.
Elapsed: 643 sec
u=8.43 s=26.63 cu=281.27 cs=143.48 scripts=2437 tests=1120821

解决:
从root切换回lfs,再度编译

Python-3.9.6

1
2
3
4
5
6
7
8
9
10
tar -xvf Python-3.9.6.tar.xz
cd Python-3.9.6

time { ./configure --prefix=/usr \
--enable-shared \
--without-ensurepip && make && make install;}

cd ..
rm -rf Python-3.9.6

Texinfo-6.8

1
2
3
4
5
6
7
8
9
10
11
tar -xvf texinfo-6.8.tar.xz
cd texinfo-6.8

sed -e 's/__attribute_nonnull__/__nonnull/' \
-i gnulib/lib/malloc/dynarray-skeleton.c

time { ./configure --prefix=/usr && make && make install;}

cd ..
rm -rf texinfo-6.8

Util-linux-2.37.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
tar -xvf util-linux-2.37.2.tar.xz
cd util-linux-2.37.2

mkdir -pv /var/lib/hwclock

time { ./configure ADJTIME_PATH=/var/lib/hwclock/adjtime \
--libdir=/usr/lib \
--docdir=/usr/share/doc/util-linux-2.37.2 \
--disable-chfn-chsh \
--disable-login \
--disable-nologin \
--disable-su \
--disable-setpriv \
--disable-runuser \
--disable-pylibmount \
--disable-static \
--without-python \
runstatedir=/run && make && make install;}

cd ..
rm -rf util-linux-2.37.2

清理和备份临时系统

1
2
3
4
5
6
rm -rf /usr/share/{info,man,doc}/*

find /usr/{lib,libexec} -name \*.la -delete

rm -rf /tools

用快照备份系统,不建议用书中方式。