5.12. GCC-4.3.2 - 第二遍

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

预计编译时间: 6.5 SBU
所需磁盘空间: 865 MB

5.12.1. 重新安装 GCC

用于测试 GCC 和 Binutils 的工具 — Tcl、Expect 以及 DejaGUN — 已经安装好了。现在可以重新安装 GCC 和 Binutils,将它们连接到新的 Glibc 上,并做相关的测试(如果做本章的测试)。请注意,这些测试套件严重依赖于正常运作的伪终端(PTY),这些伪终端通常是由宿主系统的 devpts 文件系统提供。因此请运行下面的小测试,检查宿主系统的 devpts 文件系统是否设置正确:



expect -c "spawn ls"


如果得到这样的提示:



The system has no more ptys.


Ask your system administrator to create more.


说明宿主系统没有设置好 PTYs,这样做 GCC 和 Binutils 的测试就没有意义了。想要解决该问题请参阅 http://www.linuxfromscratch.org//lfs/faq.html#no-ptys 获取更多信息。

正如在前面第 5.8 节 “调整工具链”里解释的,在一般情况下,GCC 会运行 fixincludes 脚本来修正可能存在问题的头文件。当 GCC-4.3.2 和 Glibc-2.8-20080929 都已经安装好的情况下,相应的头文件就不再需要修正了,也就不再需要 fixincludes 文件了。另外根据前面的说明,该脚本的运行会修正宿主系统中存在问题的头文件,并修正后安装 GCC 的专属头文件目录,这会影响编译环境。运行下面命令禁止 fixincludes 脚本运行:



cp -v gcc/Makefile.in{,.orig}


sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig > gcc/Makefile.in


第 5.5 节 “GCC-4.3.2 - 第一遍”中,进行的 bootstrap 编译使用了 -fomit-frame-pointer 编译选项,而非 bootstrap 编译则默认忽略了该选项,所以需要使用下面的 sed 命令来确保在非 bootstrap 编译时也同样使用 -fomit-frame-pointer 选项,以保持编译的一致性:



cp -v gcc/Makefile.in{,.tmp}


sed 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \


  > gcc/Makefile.in


下面的命令将会更改 GCC 使用的默认动态连接器的位置,让其使用我们安装在 /tools 目录下的。该命令还将 /usr/include 从 GCC 的头文件搜索路径中删除。现在做这个工作而不是在安装后调整 specs 文件,这保证了在实际编译 GCC 的过程中就使用新的动态连接器。也就是编译过程中生成的所有新的二进制文件都会连接到新的 Glibc。



for file in $(find gcc/config -name linux64.h -o -name linux.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_INCLUDE_DIR


#define STANDARD_INCLUDE_DIR 0" >> $file


  touch $file.orig


done


如果觉得上面的太长,不好理解。我们分解开来解释,首先寻找 gcc/config 目录下的所有名为 linux.hlinux64.h 的文件,复制这些文件并改名,在其后面添加后缀“.orig”,第一个 sed 表达式在这些文件中的每一处 “/lib/ld”、“/lib64/ld” 或 “/lib32/ld” 前面添加 “/tools”。第二个表达式替换每一个硬编码的 “/usr”。接着,我们定义一个语句,将头文件搜索路径移动到文件的最后。最后,使用 touch 来更新复制文件的时间戳。由于可能运行多次,使用 cp -u 可以防止原来的文件被更改。

如同第一次一样,GCC 需要 GMP 和 MPFR 包,解压它们,改名并移动到所需的目录:



tar -jxf ../mpfr-2.3.2.tar.bz2


mv mpfr-2.3.2 mpfr


tar -jxf ../gmp-4.2.4.tar.bz2


mv gmp-4.2.4 gmp


按照 GCC 建议的那样,再次创建一个独立的编译目录:



mkdir -v ../gcc-build


cd ../gcc-build


在编译GCC之前记得,取消任何优化编译选项:

现在开始准备编译:



../gcc-4.3.2/configure --prefix=/tools \


    --with-local-prefix=/tools --enable-clocale=gnu \


    --enable-shared --enable-threads=posix \


    --enable-__cxa_atexit --enable-languages=c,c++ \


    --disable-libstdcxx-pch --disable-bootstrap


配置选项的含义:

--enable-clocale=gnu

该选项保证在任何情况下都会为 C++ 库选择正确的 locale 模块。如果配置脚本发现安装了 de_DE locale,它能选择正确的 gnu locale 模块,但是如果没有安装 de_DE,就会选择不正确的通用 locale 模块,这可能构建与应用程序二进制接口(ABI)不兼容的 C++ 库。

--enable-threads=posix

使 C++ 异常处理能处理多线程代码。

--enable-__cxa_atexit

为本地静态和全局函数注册 C++ 析构函数时使用 __cxa_atexit 而不是 atexit,这是为了使对析构函数的处理完全符合标准规定。这还会影响 C++ 的 ABI,从而使 C++ 共享库和 C++ 程序可以在其他 Linux 发行版中使用。

--enable-languages=c,c++

保证编译 C 和 C++ 的编译器。

--disable-libstdcxx-pch

不为 libstdc++ 构建预编译头文件(PCH),这会占用很多空间,但我们用不到它。

--disable-bootstrap

GCC 默认采用 bootstrap 方法编译自身,但是我们已经能提供一个稳健的编译器,不需要每次都 bootstrap。

编译软件包:



make


现在编译完成了,如前所述,在本章为了一个临时工具运行测试程序不是强制的。如果想运行 GCC 的测试套件,使用下列命令:



make -k check


参数 -k 用来保证 GCC 在遇到错误时不会停下来,直到全部测试完成。GCC 的测试套件非常全面,几乎肯定会出些错误。

关于特别重要的测试的出错讨论,请参考第 6.14 节 “GCC-4.3.2”

安装 GCC:



make install


[小心]

小心

现在,有必要停下来检查新工具链能够完成预期功能(编译和链接),运行下面命令完成合理的检查:



echo 'main(){}' > dummy.c


cc dummy.c


readelf -l a.out | grep ': /tools'


如果工作一切正常,应该不会出错,最后一个命令的输出应该是:



[Requesting program interpreter:


    /tools/lib/ld-linux.so.2]


注意,/tools/lib 应该是动态链接器的前缀。

如果输出和上面的不一样,或者根本没有输出,就一定是出错了。返回前面的步骤查找问题所在,在纠正这个问题之前不要继续往下做。首先,重新做上一个检查,但用 gcc 替换 cc,如果这次输出正确了,说明链接到 cc 的符号链接有问题,返回第 5.5 节 “GCC-4.3.2 - 第一遍”创建符号链接。下一步,确保 PATH 变量的正确,这可以通过运行 echo $PATH,验证 /tools/bin是否在输出列表的最开头。如果 PATH 变量出错,可能是因为你不是作为 lfs 用户登入,也可能是在做第 4.4 节 “设置编译环境”时出错了。另外一个原因可能是上面修正 specs 文件时出错,如果这样,重新修改 specs 文件,复制粘贴时要小心仔细。

一切正常之后,清理测试文件:



rm -v dummy.c a.out


关于此软件包的详细信息,位于第 6.14.2 节 “GCC 的内容”


Host by Unixetc