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