5.10. GCC-8.2.0 - 第 2 遍

GCC 软件包包括 GNU 编译器集,其中有 C 和 C++ 的编译器。

大致构建用时: 14 SBU
所需磁盘空间: 3.4 GB

5.10.1. 安装 GCC

我们第一次编译 GCC 的时候安装了一些内部系统头文件。其中的一个 limits.h 会反过来包括对应的系统头文件 limits.h,在我们的例子中,是 /tools/include/limits.h 。但是,第一次编译 gcc 的时候 /tools/include/limits.h 并不存在,因此 GCC 安装的内部头文件只是部分的自包含文件,并不包括系统头文件的扩展功能。这足以编译临时 libc,但是这次编译 GCC 要求完整的内部头文件。使用和正常情况下 GCC 编译系统使用的相同的命令创建一个完整版本的内部头文件:

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

再一次更改 GCC 的默认动态链接器的位置,使用安装在 /tools 的那个。

for file in gcc/config/{linux,i386/linux{,64}}.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

如果是在 x86_64 环境上构建,为 64 位库改变默认目录名至「lib」:

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

和第一次编译 GCC 一样,它要求 GMP、MPFR 和 MPC 软件包。解压 tar 包并把它们重名为到所需的文件夹名称:

tar -xf ../mpfr-4.0.2.tar.xz
mv -v mpfr-4.0.2 mpfr
tar -xf ../gmp-6.1.2.tar.xz
mv -v gmp-6.1.2 gmp
tar -xf ../mpc-1.1.0.tar.gz
mv -v mpc-1.1.0 mpc

再次创建独立的编译文件夹:

mkdir -v build
cd       build

在开始编译 GCC 之前,记住取消所有会覆盖默认优化选项的环境变量。

准备编译 GCC:

CC=$LFS_TGT-gcc                                    \
CXX=$LFS_TGT-g++                                   \
AR=$LFS_TGT-ar                                     \
RANLIB=$LFS_TGT-ranlib                             \
../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

新配置选项的含义:

--enable-languages=c,c++

这个选项确保编译了 C 和 C++ 编译器。

--disable-libstdcxx-pch

不为 libstdc++ 编译预编译的头文件(PCH)。这会花费很多时间,却对我们没有用处。

--disable-bootstrap

对于原生编译的 GCC,默认是做一个「引导」构建。这不仅会编译 GCC 一次,而是会编译很多次。使用初次编译的程序去编译其自身第二次,然后同样地进行第三次。比较第二次和第三次迭代确保其能完美地复制自身。这也能预示编译是正确地。但是,LFS 的构建方法能够提供一个稳定的编译器,避免每次都需要重新引导。

编译软件包:

make

安装软件包:

make install

作为画龙点睛,这里创建一个符号链接。很多程序和脚本执行 cc 而不是 gcc 来保证程序的通用性,并且在所有的 Unix 类型的系统上都能用,而非仅局限于安装了 GCC 的 Unix 类型的系统。运行 cc 使得系统管理员不用考虑要安装那种 C 编译器:

ln -sv gcc /tools/bin/cc
[Caution]

Caution

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

echo 'int main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'

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

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

注意 32 位机器的动态链接是 /tools/lib/ld-linux.so.2。

如果输出不是像上面那样或者根本就没有输出,那么可能某些地方出错了。调查并回溯这些步骤,找出问题所在并改正它。在继续之前必须解决这个问题。首先,使用 gcc 而不是 cc 再次进行全面的检查。如果能运行,就符号链接 /tools/bin/cc 就不见了。像上面介绍的那样新建符号链接。下一步,确认 PATH 是正确的。这能通过运行 echo $PATH 检验,验证 /tools/bin 在列表的前面。如果 PATH 是错误的,这意味着你可能不是以 lfs 用户的身份登录或者在前面 Section 4.4, “设置环境” 中某些地方出现了错误。

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

rm -v dummy.c a.out

该软件包的详细信息请参见: Section 6.21.2, “GCC 软件包内容”