2.2.8 构建完整的交叉编译器

现在目标系统的C库已经构建完成,我们有条件编译完整的编译器了。进入GCC的编译目录,清除临时编译的文件,重新配置GCC,与第一阶段的配置并无本质区别,但是把第一阶段禁掉的一些特性打开了。

2.2.8 构建完整的交叉编译器 - 图1

注意,这次是编译最终的交叉编译器,所以安装在$CROSS_TOOL目录下,而不是$CROSS_GCC_TMP目录下。虽然GCC支持多种编译器,但是我们只需要C和C++编译器。另外,我们要求编译器支持posix线程。

在配置完成后,使用如下命令编译并安装:

2.2.8 构建完整的交叉编译器 - 图2

最终的交叉编译器安装的主要文件如下:

(1)驱动程序

GCC安装的最主要的是交叉编译器的驱动程序,包括i686-none-linux-gnu-gcc、i686-none-linux-gnu-g++等。

(2)目标系统的库和头文件

GCC中也包含了一些用于目标系统的运行时库及头文件,它们安装在$CROSS_TOOL/i686-none-linux-gnu目录下。在该目录下,子目录lib存放包括目标系统的运行时库以及供目标系统编译程序使用的静态库,子目录include下包含开发目标系统上的程序需要的C++头文件。

(3)helper program

前面我们提到,gcc仅仅是一个驱动程序,它将调用具体的程序完成具体的任务,这些程序被GCC安装在libexec目录下,典型的有编译器cc1,链接过程调用的collect2等。

libexec与sbin/bin目录下存放的可执行文件的一个区别是:sbin/bin目录下的可执行文件一般是用户使用的;而libexec目录下的可执行文件一般是由某个程序或工具使用的,所以一般称为"helper program"。

(4)freestanding实现文件

前面我们提到,C99标准定义了两种实现方式:一种称为"hosted implementation",支持全部C标准,包括语言标准以及库标准;另外一种是"freestanding implementation"。在lib目录下的头文件即为"freestanding implementation"实现标准要求的头文件。

(5)启动文件

与C++相关的启动文件在GCC中,包括crtbegin.o、crtend.o等。

讨论完C库和编译器后,我们看到,无论是C库,还是GCC都各自安装了头文件、运行库,GCC还安装了一些内部使用的可执行程序。那么在编译程序时,GCC是怎么找到这些文件的呢?答案就是GCC内部定义的两个环境变量LIBRARY_PATH和COMPILER_PATH。GCC会根据用户的一些配置参数,包括—target、—with-sysroot等设置这些环境变量的值。我们可以在编译程序时,使用参数"-v"查看这两个变量的值。

2.2.8 构建完整的交叉编译器 - 图3

比如库的搜索路径,根据LIBRARY_PATH的定义,显然,既包括GCC安装的库的路径/vita/cross-tool/i686-none-linux-gnu/lib,又包括Glibc安装的库的路径/vita/sysroot/usr/lib。