关于本软件包的更多信息可以在 第 6.21.2 节 “GCC 的内容” 中找到。
GCC 软件包包含 GNU 编译器集合,其中有 C 和 C++ 编译器。
第一次构建的 GCC 安装了若干内部系统头文件,其中有一个 limits.h
。一般来说, 它应该包含对应的系统头文件,对于我们的特例而言,就是
/tools/include/limits.h
。 然而,在第一次构建
GCC 的时候,它还不存在, 因此 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
再一次地,改变 GCC 的默认动态链接器,使其使用 /tools
中的动态链接器:
for file in gcc/config/{linux,i386/linux{,64}}.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
如果是在 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 时一样,它需要 GMP、MPFR 和 MPC 三个包。 解压它们的源码包,并将它们移动到 GCC 要求的目录名:
tar -xf ../mpfr-4.0.1.tar.xz mv -v mpfr-4.0.1 mpfr tar -xf ../gmp-6.1.2.tar.xz mv -v gmp-6.1.2 gmp tar -xf ../mpc-1.1.0.tar.gz mv -v mpc-1.1.0 mpc
再次创建一个独立的构建目录:
mkdir -v build cd build
在开始构建 GCC 前,记得清除所有覆盖默认优化开关的环境变量。
现在准备编译 GCC:
CC=$LFS_TGT-gcc \ CXX=$LFS_TGT-g++ \ AR=$LFS_TGT-ar \ RANLIB=$LFS_TGT-ranlib \ ../configure \ --prefix=/tools \ --with-local-prefix=/tools \ --with-native-system-header-dir=/tools/include \ --enable-languages=c,c++ \ --disable-libstdcxx-pch \ --disable-multilib \ --disable-bootstrap \ --disable-libgomp
配置选项的含义:
--enable-languages=c,c++
该选项保证只构建 C 和 C++ 编译器。
--disable-libstdcxx-pch
不构建 libstdc++
的预编译头文件,它占据大量空间,而且我们用不到它。
--disable-bootstrap
对于 GCC 的本地构建,默认会进行自举 (bootstrap) 构建。 这种构建方式不仅编译 GCC ,还会将它编译多次。 它使用第一轮编译得到的程序,将自身再编译一次, 然后再用第二轮编译得到的程序将自身编译第三次。 第二次和第三次的结果被比较, 从而确认 GCC 可以没有缺陷地重新编译它自己, 这就表明编译过程准确无误。然而, LFS 的构建方法能够提供一个坚实的编译器,而不需要每次都进行自举。
编译该软件包:
make
安装该软件包:
make install
最后,还需要创建一个符号链接。许多程序和脚本运行 cc 而不是 gcc, 因为前者能够保证程序的通用性,使它可以在所有 UNIX 系统上使用, 无论是否安装了 GNU C 编译器。运行 cc 可以将安装哪种 C 编译器的选择权留给系统管理员。
ln -sv gcc /tools/bin/cc
在此时,很有必要暂停构建过程,确认新工具链的基本功能 (编译和链接)能够如同我们期望的那样工作。 执行以下命令,进行完整性检查:
echo 'int main(){}' > dummy.c cc dummy.c readelf -l a.out | grep ': /tools'
如果一切正常,这些命令应该不产生错误, 且最后一行命令的输出格式应该和下面相同:
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
注意,在 32 位机器上,动态链接器为 /tools/lib/ld-linux-so.2
。
如果输出并不像上面展示的那样,或者根本没有输出, 则表明出现了问题。检查并重新跟踪各个步骤,找到问题的原因并纠正它。
这个问题在继续构建前必须解决。首先,使用 gcc 命令代替 cc,再次进行完整性检查。 如果这次编译器正常工作,则说明
cc
符号链接不存在, 按照之前的说明安装该符号链接。另外,还要确认
PATH
环境变量正确。运行 echo $PATH 命令, 确认 /tools/bin
出现在列表的开头。如果 PATH
是错的, 表明你很可能没有以用户 lfs
的身份登录, 或者在 第 4.4 节 “配置环境” 的过程中出现了问题。
在一切检查顺利后,即可删除测试文件:
rm -v dummy.c a.out
关于本软件包的更多信息可以在 第 6.21.2 节 “GCC 的内容” 中找到。