6.17. GCC-4.8.2

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

预计构建时间: 55.6 SBU
磁盘空间需求: 2.2 GB

6.17.1. 安装 GCC

第 5.10 节 “GCC-4.8.2 - 第 2 遍” 相同,应用以下 sed 命令强制构建使用 -fomit-frame-pointer 编译器标记以确保编译器构建稳定:

case `uname -m` in
  i?86) sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in ;;
esac

还要修复一个检验 Makefile 中的错误,并禁用 g++ libmudflap 测试套件中的一个测试:

sed -i -e /autogen/d -e /check.sh/d fixincludes/Makefile.in 
mv -v libmudflap/testsuite/libmudflap.c++/pass41-frag.cxx{,.disable}

GCC 文档推荐在源代码目录外另建目录构建 GCC:

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

准备编译 GCC:

SED=sed                          \
../gcc-4.8.2/configure           \
     --prefix=/usr               \
     --enable-shared             \
     --enable-threads=posix      \
     --enable-__cxa_atexit       \
     --enable-clocale=gnu        \
     --enable-languages=c,c++    \
     --disable-multilib          \
     --disable-bootstrap         \
     --with-system-zlib

注意对于其他语言,还有一些没有满足的前提条件。编译所有 GCC 支持语言的指令见 BLFS。

新的配置选项的含义:

SED=sed

设置这个环境变量以避免一个到 /tools/bin/sed 的硬编码路径。

--with-system-zlib

此选项告诉 GCC 链接至系统上安装的 Zlib 副本而不是其内部的副本。

编译软件包:

make
[重要]

重要

本节中 GCC 的测试套件是十分重要的,任何情况下都不要跳过。

GCC 的测试套件中有一组测试已知会爆栈。在运行测试之前增大栈尺寸:

ulimit -s 32768

测试结果,但在出错时不停止:

make -k check

要获取测试套件结果的摘要,运行:

../gcc-4.8.2/contrib/test_summary

如果只要摘要,将结果以管道传送给 grep -A7 Summ

可以将结果与位于 http://www.linuxfromscratch.org/lfs/build-logs/7.5/http://gcc.gnu.org/ml/gcc-testresults/ 的样例进行比对。

总是会有几个不期待的失败无法避免。GCC 开发者通常了解这些问题,但还没有解决。特别地,libmudflap 测试已知由于 GCC 中的一个漏洞 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20003) 而特别麻烦。只要测试结果没有与以上 URL 中的相差过于悬殊,都可以安全继续。

安装软件包:

make install

Some packages expect the C preprocessor to be installed in the /lib directory. To support those packages, create this symlink:

ln -sv ../usr/bin/cpp /lib

很多软件包使用 cc 这个名字调用 C 编译器。要支持这些软件包,创建一个符号链接:

ln -sv gcc /usr/bin/cc

现在我们最终的工具链到位了,再次确保编译和链接正常工作就十分重要。我们要进行与本章中进行过的相同的稳定性测试:

echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

如果一切工作正常,就不应该出错,最后一条命令的输出 (允许动态链接器名称中有针对平台的差异) 应为:

[Requesting program interpreter: /lib/ld-linux.so.2]

现在确保设置为使用正确的起始文件:

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log

如果一切工作正常,就不应该出错,最后一条命令的输出应为:

/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/../../../crtn.o succeeded

取决于你的计算机架构,以上信息可能会有轻微差异,差异通常位于 /usr/lib/gcc 之后的目录名称。如果你的计算机是 64 位系统,你还可能看到字符串末尾出现一个名为 lib64 的目录。此处的重点是 gcc/usr/lib 目录中找到了全部三个 crt*.o 文件。

检查一下编译器是否寻找正确的头文件:

grep -B4 '^ /usr/include' dummy.log

此命令应该成功返回并给出以下输出:

#include <...> search starts here:
 /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include
 /usr/local/include
 /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include-fixed
 /usr/include

再次注意,以你的目标三联字串命名的目录可能会不同。取决于你的架构。

[注意]

注意

对于版本 4.3.0,GCC 现在无条件安装 limits.h 文件至私有的 include-fixed 目录,这个目录需要到位。

下一步检查新的链接器使用正确的搜索路径:

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

如果一切工作正常,就不应该出错,最后一条命令的输出 (允许目标三联字串中有针对平台的差异) 应为:

SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

64 位系统会有几个额外的目录。例如这是 x86_64 计算机的输出:

SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

下一步确认我们使用的是正确的 libc:

grep "/lib.*/libc.so.6 " dummy.log

如果一切工作正常,就不应该出错,最后一条命令的输出 (允许 64 位宿主上有 lib64 目录) 应为:

attempt to open /lib/libc.so.6 succeeded

最后,确保 GCC 使用正确的动态链接器:

grep found dummy.log

如果一切工作正常,就不应该出错,最后一条命令的输出 (允许动态链接器名称中有针对平台的差异、64 位宿主上有 lib64 目录) 应为:

found ld-linux.so.2 at /lib/ld-linux.so.2

如果输出不如上文所示或者根本没有输出,那么一定有某个地方严重出错了。回溯步骤,找出问题并且修正。最可能出现的原因是 specs 文件调节出错。在进行下一步之前一定要解决所有问题。

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

rm -v dummy.c a.out dummy.log

最后,移动一个位置不正确的文件:

mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

6.17.2. GCC 的内容

安装的程序: c++, cc (链接到 gcc), cpp, g++, gcc, gcc-ar, gcc-nm, gcc-ranlib 和 gcov
安装的库: libasan.{a,so}, libatomic.{a,so}, libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so}, libiberty.a, libitm.{a,so}, liblto_plugin.so, libmudflap.{a,so}, libmudflapth.{a,so}, libquadmath.{a,so}, libssp.{a,so}, libssp_nonshared.a, libstdc++.{a,so}, libsupc++.a 和 libtsan.{a,so}
安装的目录: /usr/include/c++, /usr/lib/gcc, /usr/libexec/gcc, /usr/share/gcc-4.8.2

简述

c++

C++ 编译器

cc

C 编译器

cpp

C 预处理器;被编译器用于展开源文件中的 #include、#define 以及类似的类似语句

g++

C++ 编译器

gcc

C 编译器

gcc-ar

ar 的一个封装,在命令行中加入一个插件。此程序只用于添加 链接时优化,对于默认构建选项并没有什么用处

gcc-nm

nm 的一个封装,在命令行中加入一个插件。此程序只用于添加 链接时优化,对于默认构建选项并没有什么用处

gcc-ranlib

ranlib 的一个封装,在命令行中加入一个插件。此程序只用于添加 链接时优化,对于默认构建选项并没有什么用处

gcov

一个覆盖测试工具;用于分析程序获知优化在何处效果最好

libasan

地址清理器运行时库

libgcc

包含用于 gcc 的运行时支持

libgcov

在 GCC 获得启用分析的指令时此库链接到程序

libgomp

GNU 实现的多平台 OpenMP 共享内存并行编程,用于 C/C++ 和 Fortran

libiberty

包含被用于各种 GNU 程序,包括 getoptobstackstrerrorstrtolstrtoul 的套件

liblto_plugin

GCC 的链接时优化插件,允许 GCC 在多个编译单元之间进行优化

libmudflap

包含支持 GCC 的边界检查功能的途径

libquadmath

GCC 四精度数学库 API

libssp

包含支持 GCC 防爆栈保护功能的套件

libstdc++

标准 C++ 库

libsupc++

为 C++ 程序设计语言提供支持的套件

libtsan

线程清理器运行时库