5.5. GCC-9.2.0 - 第 1 遍

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

大致构建用时: 12 SBU
所需磁盘空间: 3.1 GB

5.5.1. 安装交叉编译的 GCC

现在 GCC 需要 GMP、MPFR 和 MPC 软件包。在你的主机发行版中可能并不包括这些软件包,它们将和 GCC 一起编译。将每个解压软件包到 GCC 的目录下,并重命名解压后得到的目录,以便 GCC 编译过程中能自动使用这些软件:

[注意]

注意

读者经常对本章节产生误解。过程与之前的章节(软件包构建说明)中提到的一样。首先从源目录中解压 gcc 的源码包,然后进入创建的目录中。接着才可以执行下面的指令。

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

下面的指令将会修改 GCC 默认的动态链接器的位置,安装到 /tools 目录中的。并将 /usr/include 从 GCC 的 include 检索路径中移除。执行:

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

如果上面的内容看起来有些难以理解,那让我们慢慢消化吧。首先,我们复制文件 gcc/config/linux.hgcc/config/i386/linux.h,和 gcc/config/i368/linux64.h,给复制的文件加上「.orig」后缀。然后第一个 sed 表达式在每个「/lib/ld」,「/lib64/ld」或者「/lib32/ld」实例前面增加「/tools」,第二个 sed 表达式替换「/usr」的硬编码实例。然后,我们添加这改变默认 startfile 前缀到文件末尾的定义语句。注意「/tools/lib/」后面的「/」是必须的。最后,我们用 touch 更新复制文件的时间戳。当与 cp -u 一起使用时,可以防止命令被无意中运行两次造成对原始文件意外的更改。

最后,在 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 手册建议在源目录之外一个专门的编译目录中编译 GCC:

mkdir -v build
cd       build

准备编译 GCC:

../configure                                       \
    --target=$LFS_TGT                              \
    --prefix=/tools                                \
    --with-glibc-version=2.11                      \
    --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-libquadmath                          \
    --disable-libssp                               \
    --disable-libvtv                               \
    --disable-libstdcxx                            \
    --enable-languages=c,c++

配置选项的含义:

--with-newlib

由于还没有可用的 C 库,这确保编译 libgcc 时定义了常数 inhibit_libc。这可以防止编译任何需要 libc 支持的代码。

--without-headers

在创建完整的交叉编译器时,GCC 要求标准头文件和目标系统兼容。对于我们的目的来说,不需要这些头文件。这个选项可以防止 GCC 查找它们。

--with-local-prefix=/tools

GCC 会查找本地已安装的 include 文件的系统位置。默认是 /usr/local。把它设置为 /tools 能把主机位置中的 /usr/local 从 GCC 的搜索路径中排除。

--with-native-system-header-dir=/tools/include

GCC 默认会在 /usr/include 中查找系统头文件。和 sysroot 选项一起使用,会转换为 $LFS/usr/include。在后面两个章节中头文件会被安装到 $LFS/tools/include 。这个选项确保 gcc 能正确找到它们。第二次编译 GCC 时,同样的选项可以保证不会去寻找主机系统的头文件。

--disable-shared

这个选项强制 GCC 静态链接到它的内部库。我们这样做是为了避免主机系统可能出现的问题。

--disable-decimal-float, --disable-threads, --disable-libatomic, --disable-libgomp, --disable-libquadmath, --disable-libssp, --disable-libvtv, --disable-libstdcxx

这些选项取消了对十进制浮点数扩展、线程化、libatomic、libgomp、libquadmath、libssp、libvtv、libcilkrts 和 C++ 标准库的支持。这些功能在编译交叉编译器的时候会导致编译失败,对于交叉编译临时 libc 来说也没有必要。

--disable-multilib

在 x86_64 机器上,LFS 还不支持 multilib 配置。这个选项对 x86 来说无害。

--enable-languages=c,c++

这个选项确保只编译 C 和 C++ 编译器。这些是现在唯一需要的语言。

运行命令编译 GCC:

make

现在编译完成了。在这里,通常会运行测试套件,但正如前面提到的,测试套件框架还没有准备好。在此进行测试的并没有太多好处,因为第一遍编译的程序很快会被取代。

安装软件包:

make install

该软件包的详细信息请参见: 第 6.21.2 节 「GCC 软件包内容」