6.21.1. 安装 GCC
在 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 头文件:
rm -f /usr/lib/gcc
GCC 文档推荐在专用的构建目录中构建 GCC:
mkdir -v build
cd build
准备安装 GCC:
SED=sed \
../configure --prefix=/usr \
--enable-languages=c,c++ \
--disable-multilib \
--disable-bootstrap \
--disable-libmpx \
--with-system-zlib
请注意,对于其他语言,还有一些尚未满足的依赖项。 阅读BLFS
手册, 以了解如何构建 GCC 支持的所有语言。
新的配置选项的含义:
-
SED=sed
-
设定该环境变量,防止路径 /tools/bin/sed 被硬编码到编译结果中。
-
--disable-libmpx
-
这个开关告诉 GCC 不要构建 mpx (内存保护扩展), 它在一些处理器上会导致问题,且在下一个 GCC
版本中已被移除。
-
--with-system-zlib
-
该选项使得 GCC 链接到系统安装的 Zlib 库,而不是它自带的 Zlib 副本。
编译该软件包:
make
重要
本节中 GCC 的测试套件被认为是关键的,无论如何不能跳过。
已知 GCC 测试套件中的一组测试可能耗尽栈空间, 因此运行测试前要增加栈空间:
ulimit -s 32768
删除一个已知会导致问题的测试:
rm ../gcc/testsuite/g++.dg/pr83239.C
以非特权用户身份测试编译结果,但出错时继续执行其他测试:
chown -Rv nobody .
su nobody -s /bin/bash -c "PATH=$PATH make -k check"
输入以下命令查看测试结果的摘要:
../contrib/test_summary
如果只想看摘要,将输出用管道送至 grep -A7
Summ
。
可以将结果与 http://www.linuxfromscratch.org/lfs/build-logs/8.3/
和 https://gcc.gnu.org/ml/gcc-testresults/
的结果进行比较。
少量意外的失败有时无法避免,GCC 开发者一般知道这类问题, 但尚未解决它们。 我们可以继续安全地构建系统,除非测试结果和以上 URL
的结果截然不同。
注意
在某些 AMD 处理器上,一些特定的内核配置可以导致 gcc.target/i386/mpx 中的 1100
多个测试失败(它们被设计为在较新的 Intel 处理器上测试 MPX 选项)。在 AMD 处理器上可以安全地忽略这些失败。
另外,如果在内核配置中没有启用 MPX,即使在支持 MPX 的 Intel CPU 上, 这些测试也会失败。
安装该软件包:
make install
创建一个 FHS
因 “历史原因”
要求的符号链接:
ln -sv ../usr/bin/cpp /lib
许多软件包使用 cc 调用 C
编译器。为了满足它们, 创建一个符号链接:
ln -sv gcc /usr/bin/cc
创建一个兼容性符号链接,以支持在构建程序时使用链接时优化(LTO):
install -v -dm755 /usr/lib/bfd-plugins
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/8.2.0/liblto_plugin.so \
/usr/lib/bfd-plugins/
现在最终的工具链已经就位, 重要的是再次确认编译和链接像我们期望的一样正常工作。 再一次执行之前进行过的完整性检查:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
上述命令不应该出现错误,最后一行命令输出的结果应该 (不同平台的动态链接器名称可能不同)是:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
下面确认我们的设定能够使用正确的启动文件:
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
以上命令应该输出:
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/crt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/crtn.o succeeded
以上结果可能随您的机器体系结构不同而略微不同, 区别一般是 /usr/lib/gcc
之后的目录名。我们关注的重点是, gcc 应该在 /usr/lib
目录中找到所有三个 crt*.o
文件。
确认编译器能正确查找头文件:
grep -B4 '^ /usr/include' dummy.log
该命令应当输出:
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed
/usr/include
同样要注意以您的目标三元组命名的目录根据您体系结构的不同, 可能和以上不同。
下一步确认新的链接器使用了正确的搜索路径:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
那些包含 '-linux-gnu' 的路径应该忽略, 除此之外,以上命令应该输出:
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
在 32 位系统上可能显示一些不同的目录,例如下面是 i686 机器上的输出:
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");
之后确认我们使用了正确的 libc:
grep "/lib.*/libc.so.6 " dummy.log
以上命令应该输出:
attempt to open /lib/libc.so.6 succeeded
最后,确认 GCC 使用了正确的动态链接器:
grep found dummy.log
以上命令应该输出(不同平台的动态链接器名称可能不同):
found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.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