%general-entities; ]> gcc-pass1 &gcc-version;
&gcc-url;
GCC-&gcc-version; - 第一遍 GCC tools, pass 1 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../chapter06/gcc.xml" xpointer="xpointer(/sect1/sect2[1]/para[1])"/> <segmentedlist> <segtitle>&buildtime;</segtitle> <segtitle>&diskspace;</segtitle> <seglistitem> <seg>&gcc-ch5p1-sbu;</seg> <seg>&gcc-ch5p1-du;</seg> </seglistitem> </segmentedlist> </sect2> <sect2 role="installation"> <title>安装交叉工具链中的 GCC 目前 GCC 依赖于 GMP、MPFR 和 MPC 这三个包。 由于宿主发行版未必包含它们,我们将它们和 GCC 一同构建。 将它们都解压到 GCC 源码目录中,并重命名解压出的目录, 这样 GCC 构建过程就能自动使用它们: 对于本章内容有一些很常见的误解。该软件包的构建过程就像之前 () 解释的那样, 首先解压 GCC 压缩包,切换到解压出的目录中,再执行下面的命令。 tar -xf ../mpfr-&mpfr-version;.tar.xz mv -v mpfr-&mpfr-version; mpfr tar -xf ../gmp-&gmp-version;.tar.xz mv -v gmp-&gmp-version; gmp tar -xf ../mpc-&mpc-version;.tar.gz mv -v mpc-&mpc-version; mpc 下面的命令修改 GCC 的默认动态链接器位置,以使用 /tools 中的动态链接器。 同时,从 GCC 的头文件搜索路径中删除 /usr/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.hgcc/config/i386/linux64.h, 将它们备份为名称是原文件名加上 .orig 后缀的文件。 然后第一个 sed 表达式将所有 /lib/ld/lib64/ld 或者 /lib32/ld 之前都加上 /tools,第二个将硬编码的 /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 支持的代码。 译注 这个选项对于嵌入式系统工程师来说显得很奇怪, 因为 LFS 和嵌入式系统中常用的 C 运行库 newlib 毫无关系。 参见译者和 GCC 开发者的讨论: --without-headers 在创建完整的交叉编译器时, GCC 需要与目标系统兼容的标准头文件。 由于我们的特殊目的,这些头文件并不必要。 这个开关防止 GCC 查找它们。 --with-local-prefix=/tools 本地前缀是 GCC 在系统中寻找本地安装的包含文件的位置, 它的默认值是 /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 和 C++ 标准库的支持。 在构建交叉编译器时它们的编译会失败,而且在交叉编译临时 libc 时并不需要它们。 --disable-multilib 在 x86_64 平台上,LFS 目前不支持 multilib 配置。 这个开关对于 x86 来说可有可无。 --enable-languages=c,c++ 这个选项保证只构建 C 和 C++ 编译器。目前只需要这两个语言。 执行以下命令编译 GCC: make 现在我们编译完成了 GCC。此时,通常来说应该执行测试套件。 然而正如前文所述,测试套件框架还没有就位, 而且第一遍编译的 GCC 程序很快就会被替换,运行测试套件的收益极小。 安装该软件包: make install <para>该软件包的更多细节在 <xref linkend="contents-gcc"/> 中可以找到。</para> </sect2> </sect1>