5.10. GCC-8.2.0 - 第二遍

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

估计编译时间: 11 SBU
需要硬盘空间: 3.4 GB

5.10.1. 安装 GCC

第一次构建的 GCC 安装了若干内部系统头文件,其中有一个 limits.h。一般来说, 它应该包含对应的系统头文件,对于我们的特例而言,就是 /tools/include/limits.h。 然而,在第一次构建 GCC 的时候,它还不存在, 因此 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 三个包。 解压它们的源码包,并将它们移动到 GCC 要求的目录名:

tar -xf ../mpfr-4.0.1.tar.xz
mv -v mpfr-4.0.1 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++ 的预编译头文件,它占据大量空间,而且我们用不到它。

--disable-bootstrap

对于 GCC 的本地构建,默认会进行自举 (bootstrap) 构建。 这种构建方式不仅编译 GCC ,还会将它编译多次。 它使用第一轮编译得到的程序,将自身再编译一次, 然后再用第二轮编译得到的程序将自身编译第三次。 第二次和第三次的结果被比较, 从而确认 GCC 可以没有缺陷地重新编译它自己, 这就表明编译过程准确无误。然而, LFS 的构建方法能够提供一个坚实的编译器,而不需要每次都进行自举。

编译该软件包:

make

安装该软件包:

make install

最后,还需要创建一个符号链接。许多程序和脚本运行 cc 而不是 gcc, 因为前者能够保证程序的通用性,使它可以在所有 UNIX 系统上使用, 无论是否安装了 GNU C 编译器。运行 cc 可以将安装哪种 C 编译器的选择权留给系统管理员。

ln -sv gcc /tools/bin/cc
[小心]

小心

在此时,很有必要暂停构建过程,确认新工具链的基本功能 (编译和链接)能够如同我们期望的那样工作。 执行以下命令,进行完整性检查:

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,再次进行完整性检查。 如果这次编译器正常工作,则说明 cc 符号链接不存在, 按照之前的说明安装该符号链接。另外,还要确认 PATH 环境变量正确。运行 echo $PATH 命令, 确认 /tools/bin 出现在列表的开头。如果 PATH 是错的, 表明你很可能没有以用户 lfs 的身份登录, 或者在 第 4.4 节 “配置环境” 的过程中出现了问题。

在一切检查顺利后,即可删除测试文件:

rm -v dummy.c a.out

关于本软件包的更多信息可以在 第 6.21.2 节 “GCC 的内容” 中找到。