这个包的详细信息位于 第 6.17.2 节 “GCC 的内容.”
GCC 软件包包含 GNU 编译器集,其中包括 C 和 C++ 编译器。
我们第一次构建的 GCC 已经安装了一些内部系统头文件。通常其中一个,limits.h
会反过来包含对应的系统 limits.h
头文件,也就是 /tools/include/limits.h
。然而在第一次构建 GCC 时
/tools/include/limits.h
不存在,所以 GCC
安装的内置头文件是一个部分的、自包含的文件,不包含系统头文件的扩展特性。这对于临时的 libc 已经足够了,但是这次构建的 GCC
需要完整的内置头文件。创建一个完整版本的内置头文件使用的命令与 GCC 构建系统通常情况下的行为相同:
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \ `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h
对于 x86 计算机,引导构建 GCC 使用 -fomit-frame-pointer
编译器标记。非引导构建默认会忽略这个标记,而我们的目标是产生一个和引导过完全一样的编译器。应用以下的 sed 命令强制构建使用这个标记:
case `uname -m` in i?86) sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in ;; esac
再次改变 GCC 的默认动态链接器位置以使用安装于 /tools
的副本。
for file in \ $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.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_STARTFILE_PREFIX_1 #undef STANDARD_STARTFILE_PREFIX_2 #define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/" #define STANDARD_STARTFILE_PREFIX_2 ""' >> $file touch $file.orig done
与第一次编译 GCC 相同,它需要 GMP、MPFR 和 MPC 软件包。解开压缩包并将它们移动到指定名称的目录中:
tar -Jxf ../mpfr-3.1.2.tar.xz mv -v mpfr-3.1.2 mpfr tar -Jxf ../gmp-5.1.3.tar.xz mv -v gmp-5.1.3 gmp tar -zxf ../mpc-1.0.2.tar.gz mv -v mpc-1.0.2 mpc
再创建一个独立的构建目录:
mkdir -v ../gcc-build cd ../gcc-build
在开始构建 GCC 之前,记得解除所有覆盖默认优化标记的环境变量。
现在准备编译 GCC:
CC=$LFS_TGT-gcc \ CXX=$LFS_TGT-g++ \ AR=$LFS_TGT-ar \ RANLIB=$LFS_TGT-ranlib \ ../gcc-4.8.2/configure \ --prefix=/tools \ --with-local-prefix=/tools \ --with-native-system-header-dir=/tools/include \ --enable-clocale=gnu \ --enable-shared \ --enable-threads=posix \ --enable-__cxa_atexit \ --enable-languages=c,c++ \ --disable-libstdcxx-pch \ --disable-multilib \ --disable-bootstrap \ --disable-libgomp \ --with-mpfr-include=$(pwd)/../gcc-4.8.2/mpfr/src \ --with-mpfr-lib=$(pwd)/mpfr/src/.libs
新配置选项的含义:
--enable-clocale=gnu
此选项确保在任何情况下都能给 C++ 库选择正确的区域数据模型。如果配置脚本发现安装了 de_DE 区域数据,它就会选择正确的 gnu 区域数据模型。但是如果 de_DE 区域数据没有安装,就有可能因为选中了不正确的通用区域数据模型而构建出与 ABI 不兼容的 C++ 库。
--enable-threads=posix
此项启用 C++ 多线程代码的异常处理。
--enable-__cxa_atexit
此选项允许使用 __cxa_atexit
而不是
atexit
来本地静态和全局对象注册 C++
析构函数。此选项对于完全兼容标准的析构函数处理是必要的。它也会影响 C++ ABI,而使得 C++ 程序和共享库可以与其他
Linux 发行版相互操作。
--enable-languages=c,c++
此选项确保 C 和 C++ 编译器都被构建。
--disable-libstdcxx-pch
不要给 libstdc++
构建预编译头文件。它占用很多空间,对我们还没有用。
--disable-bootstrap
对于原生 GCC 构建,默认会进行 “引导” 构建。这不是只编译 GCC,而是编译它几遍。用第一次编译的程序把自己编译第二遍,然后编译第三遍。然后比较第二遍和第三遍的产物以确保它可以不出差错地自编译。这也就表示它编译正确。然而,LFS 构建方法会提供一个固化的编译器,不用每次都引导。
编译软件包:
make
安装软件包:
make install
最后一步,创建一个符号链接。很多程序和脚本会运行 cc 而不是 gcc,用来使程序通用,在所有的 UNIX 系统上都可用,而 GNU 编译器并不总是安装。运行 cc 就给系统管理员留出了选择安装哪一个 C 编译器的自由:
ln -sv gcc /tools/bin/cc
在这里,停下来确保新工具链的基本功能 (编译和链接) 能正常工作很重要。要进行稳定性检查,运行以下命令:
echo 'main(){}' > dummy.c cc dummy.c readelf -l a.out | grep ': /tools'
如果一切工作正常,就不会出现错误,最后一条命令的输出会符合以下格式:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
留意 /tools/lib
或者 64 位计算机上的
/tools/lib64
作为动态链接器的前缀出现。
如果输出不如上文所示或者根本没有输出,那就有什么地方出错了。研究回溯刚才的步骤,查出问题并修正它。在继续之前必须解决这一问题。首先,使用
gcc 而不是
cc
再做一次完整性检查。如果能够工作,那就是 /tools/bin/cc
这个符号链接丢失了。重做这个链接。下一步,确保 PATH
正确。可以运行
echo $PATH 并检查
/tools/bin
是否在列表首位。如果 PATH
错误可能就是你未作为 lfs
用户登录或者早在 第 4.4 节 “设置工作环境” 就出现了错误。
一切正常之后,清理测试文件:
rm -v dummy.c a.out
这个包的详细信息位于 第 6.17.2 节 “GCC 的内容.”