5.5. GCC-4.9.2 - 第一遍

GCC 软件包是 GNU 编译器集合的一部分,其中包括 C 和 C++ 的编译器。

大概编译时间: 5.9 SBU
所需磁盘空间: 2.0 GB

5.5.1. 安装交叉编译的 GCC

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

[Note]

注意

有些读者对本章节内容存在误解。和之前章节中介绍的(软件包编译指南)一样,过程都是相同的。首先从源文件夹中解压 gcc tar 包 然后进入到创建的文件夹中。然后才可以执行下面的指令。

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

下面的指令将会修改 GCC 默认的动态链接器为安装在 /tools 文件夹中的。它也会从 GCC 的 include 搜索路径中移除 /usr/include。执行:

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

如果上面的看起来难以理解,让我们分开来看一下吧。首先我们找到 gcc/config 文件夹下的所有命名为 linux.h, linux64.hsysv4.h 的文件。对于找到的每个文件,我们把它复制到相同名称的文件,但增加了后缀 .orig。然后第一个 sed 表达式在每个 /lib/ld, /lib64/ld/lib32/ld 实例前面增加/tools,第二个 sed 表达式替换 /usr 的硬编码实例。然后,我们添加这改变默认 startfile 前缀到文件末尾的定义语句。注意 /tools/lib/ 后面的 / 是必须的。最后,我们用 touch 更新复制文件的时间戳。当与 cp -u 一起使用时,可以防止命令被无意中运行两次造成对原始文件意外的更改。

GCC 不能正确检测栈保护,这会导致编译 Glibc-2.21 时出现问题,用下面的命令修复这个问题:

sed -i '/k prot/agcc_cv_libc_provides_ssp=yes' gcc/configure

GCC 手册建议在源文件夹之外一个专门的编译文件夹中编译 GCC:

mkdir -v ../gcc-build
cd ../gcc-build

准备编译 GCC:

../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++

配置选项的含义:

--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-libitm, --disable-libquadmath, --disable-libsanitizer, --disable-libssp, --disable-libvtv, --disable-libcilkrts, --disable-libstdc++-v3

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

--disable-multilib

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

--enable-languages=c,c++

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

运行命令编译 GCC:

make

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

安装软件包:

make install

该软件包的详细信息在 Section 6.17.2, “GCC 软件包内容”