GCC 软件包包括 GNU 编译器集,其中有 C 和 C++ 的编译器。
大概编译时间:
63 SBU (包括测试)
需要磁盘空间:
2.9 GB
6.17.1. 安装 GCC
GCC 的文档建议在源代码目录之外一个专用的编译目录中编译 GCC:
mkdir -v ../gcc-build cd ../gcc-build
准备编译 GCC:
SED=sed \ ../gcc-4.9.2/configure \ --prefix=/usr \ --enable-languages=c,c++ \ --disable-multilib \ --disable-bootstrap \ --with-system-zlib
注意,对于其它的编程语言,现在还有一些前提条件没有准备好。可以查看 BLFS Book 了解如何编译 GCC 支持的所有语言的指令。
新配置选项的含义:
-
SED=sed
-
设置环境变量防止访问到硬编码的 /tools/bin/sed 路径。 -
--with-system-zlib
-
这个选项告诉 GCC 链接系统安装的 Zlib 库,而不是它内部自带的库。
编译软件包:
make
重要
本章节中 GCC 的测试套件至关重要,任何情况下都不能跳过。
GCC 测试套件中一个测试集的会耗尽堆栈空间,因此运行测试之前要增加栈大小:
ulimit -s 32768
测试编译结果,但不要因为出现错误就停下来:
make -k check
要查看测试套件结果的概要,运行:
../gcc-4.9.2/contrib/test_summary
如果只是查看概要,可以将输出通过管道送到 grep -A7 Summ
。
结果可以和 http://www.linuxfromscratch.org/lfs/build-logs/7.7-systemd/
以及 http://gcc.gnu.org/ml/gcc-testresults/ 上的相比较。
一些意料之外的错误总是难以避免。GCC 开发者通常意识到了这些问题,但还没有解决。除非测试结果和上面 URL 中的相差很大,不然就可以安全继续。
安装软件包:
make install
一些软件包希望 GCC 安装在 /lib
目录。为了支持那些软件包,可以建立一个符号链接:
ln -sv ../usr/bin/cpp /lib 译者注:如果还在 gcc-build 目录,这里应该是 ln -sv ../../usr/bin/cpp /lib 。
很多软件包用命令 cc 调用 C 编译器。为了满足这些软件包,创建一个符号链接:
ln -sv gcc /usr/bin/cc
增加一个兼容符号链接启用编译程序时进行链接时间优化(Link Time Optimization,LTO):
install -v -dm755 /usr/lib/bfd-plugins ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/4.9.2/liblto_plugin.so /usr/lib/bfd-plugins/
现在我们最终的工具链已经准备就绪了,再一次确认编译和链接都能像预期那样正常工作很重要。我们通过做和前面章节做过的相同的完整性检查做到这点:
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.9.2/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.9.2/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.9.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.9.2/include
/usr/local/include
/usr/lib/gcc/i686-pc-linux-gnu/4.9.2/include-fixed
/usr/include
同时,注意你的目标系统三段式后面的目录名称可能和上面的不同,这取决于你的架构。
注意
在版本 4.3.0 中,GCC 无条件安装 limits.h
文件到私有 include-fixed
目录,要求这个目录已经存在。
下一步,验证新的链接器在使用正确的搜索路径:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
可以忽略指向含有 '-linux-gnu' 的路径的引用,但最后一个命令的输出应该是:
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
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
如果输出和上面的不一样或者根本就没有任何输出,表明发生了很严重的错误。检查并回溯步骤找出问题所在并纠正它。最可能的原因是配置文件调整时出现了问题。在进入下一步之前必须解决所有的问题。
当一切都正常工作后,清理测试文件:
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,
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.9.2
简要介绍
c++ |
C++ 编译器 |
cc |
C 编译器 |
cpp |
C 预处理器;编译器用来扩展源文件中 #include、#define 以及类似语句 |
g++ |
C++ 编译器 |
gcc |
C 编译器 |
gcc-ar |
增加插件到命令行的 ar 的封装。这个程序只用于添加 "链接时间优化",在使用默认编译选项时不起作用 |
gcc-nm |
增加插件到命令行的 nm 的封装。这个程序只用于添加 "链接时间优化",在使用默认编译选项时不起作用 |
gcc-ranlib |
增加插件到命令行的 ranlib 的封装。这个程序只用于添加 "链接时间优化",在使用默认编译选项时不起作用 |
gcov |
一个覆盖测试工具;用于分析程序以决定在哪里进行优化有最大的效果 |
libasan |
Address Sanitizer(译者注:地址消毒剂,可以查看:Wiki)运行时库。 |
libgcc
|
包含用于 gcc 的运行时支持 |
libgcov
|
当指示 GCC 启用分析时该库会被链接到程序中 |
libgomp
|
用于 C/C++、Fortran 语言的多平台共享内存并行编程的 OpenMP API 的 GNU 实现 |
libiberty
|
包含多种 GNU 程序所使用的例程,包括 getopt, obstack, strerror, strtol, 和 strtoul |
liblto_plugin
|
GCC 的链接时间优化插件,允许 GCC 跨编译单元进行优化 |
libquadmath
|
GCC 四精度数学库 API |
libssp
|
包含支持 GCC 堆栈溢出保护功能的例程 |
libstdc++
|
标准 C++ 库 |
libsupc++
|
为 C++ 编程语言提供支持例程 |
libtsan
|
Thread Sanitizer(译者注:数据速率检测工具,包括一个编译器指令模块和运行时库) 运行时库 |
创建者:Gerard Beekmans
编辑者:Matthew Burgess 和 Armin K.
翻译团队:LCTT
译者/校对:ictlyh,wxy