《深入分析GCC 》——3.3 GCC源代码编译

3.3 GCC源代码编译
在获得了GCC的源代码后,为了生成目标机器上的编译器程序,需要对源代码进行编译,一般步骤包括:
(1)使用conf?igure脚本完成编译配置,生成Makef?ile文件。
(2)使用make工具编译源代码。
(3)使用make工具安装生成的编译程序等。
使用的典型脚本为:

./configure
make
make install

3.3.1 配置

这个过程一般很简单,可以直接在${GCC_SOURCE}目录下使用命令./conf?igure。该脚本会对GCC源代码编译、安装的环境进行检查,并根据conf?igure脚本的参数对编译环境进行配置,从而最终生成Makef?ile文件,作为后续make工具进行编译和安装的依据。
然而,稍微仔细分析后会发现,这又是一个非常令人烦恼的过程,原因是这个配置命令具有较多的选项。可以使用./conf?igure --help查看这些配置选项及其主要的功能说明。
下面对编译配置中的一些主要选项进行简单的说明。
(1)安装目录(Installation directories)选项:
--pref?ix=PREFIX:用来指定目标机器无关代码的安装目录,默认值为/usr/local。
--exec-pref?ix=EPREFIX:用来指定目标机器相关代码的安装目录,一般与--pref?ix选项指定的PREFIX值相同。
(2)程序名称(Program names):
--program-pref?ix=PREFIX:设置安装程序名的前缀为PREFIX。
--program-suff?ix=SUFFIX:设置安装程序名的后缀为SUFFIX。
例如,如果使用如下命令进行配置:
[GCC@host1 gcc-4.4.0]$ ./configure --program-prefix=prefix-
那么最终生成的gcc编译程序的名称将变成:/usr/local/bin/prefix-gcc,其中prefix-gcc里面的“prefix-”就是由--program-pref?ix=prefix-选项所指定的。
(3)系统类型(System types):
用来描述生成、运行及目标系统的系统类型,通常由--build、--host及--target三个选项指定,其中:
build=BUILD:指定生成(build)编译器程序的机器和操作系统平台信息。
host=HOST:指定生成的编译器程序所运行的机器和操作系统平台信息,默认值与BUILD相同。
target=TARGET:指定生成的编译器程序生成代码所运行的机器和操作系统平台信息,默认值与HOST相同。
关于这几个选项的指定,通常会有如下的几种组合方式:
1)BUILD、HOST、TARGET三者相同,这一般表示在本机进行GCC源代码的编译,生成的编译器程序GCC也运行在与本机相同的机器和操作系统平台下,并且生成的编译器编译出的目标程序也将运行在同样的系统环境中。
2)HOST与TARGET相同,但HOST与BUILD不同,这是一种典型的生成交叉编译工具的情况,即在BUILD主机环境上编译GCC源代码,生成的编译器程序将运行在HOST主机环境中,并且该编译器程序编译生成的目标文件也将运行在HOST,即TARGET环境中。
3)BUID、HOST及TARGET各不相同,这是一种最复杂的情况,也属于一种生成交叉编译工具的情况,即在BUILD主机环境上编译GCC源代码,生成的编译器程序将运行在HOST主机环境中,并且该编译器程序编译生成的目标文件将运行在另一种TARGET机器环境中。
例3-1 通过Makefile文件查看build、host及target系统的配置值
假设本例运行的主机信息如下:

[GCC@host1 gcc-4.4.0]$ uname -a
Linux host1 2.6.32-71.el6.i686 #1 SMP Fri Nov 12 04:17:17 GMT 2010 i686 i686 i386 GNU/Linux

第一种情况,在gcc-4.4.0源代码目录中直接执行./conf?igure,那么在生成Makef?ile文件中包含了如下信息:

build=i686-pc-linux-gnu
host=i686-pc-linux-gnu
target=i686-pc-linux-gnu

这种情况下,conf?igure脚本会自动根据系统的信息“猜测”出build的值,例如本例中看到的build的值为“i686-pc-linux-gnu”,而host的默认值与build相同,target的默认值与host相同。此时三者的值都是相同的,这就是上述系统类型1)中的组合方式。
第二种情况,假如要在本机上对GCC源代码进行编译,生成的编译器程序也运行在本机上,但编译器需要为arm机器生成运行代码,此时,编译配置可以如下:
[GCC@host1 gcc-4.4.0]$ ./configure --target=arm-linux-gnu
或者:

[GCC@host1 gcc-4.4.0]$ ./configure --build=i686-pc-linux-gnu --target=arm-linux-gnu

生成的Makef?ile文件都包含了如下内容:

build=i686-pc-linux-gnu
host=i686-pc-linux-gnu
target=arm-unknown-linux-gnu

此时build与host相同,即用来编译GCC的机器和将来要运行编译器的机器类型是相同的,但是编译器生成的代码却不在host主机系统上运行,而是要运行在一种arm-unknown-linux-gnu机器上,这就是一种典型的交叉编译。
(4)可选编译特性的运行与禁止。
一般使用--enable-FEATURE[=ARG]或者--disable-FEATURE表示设置该FEATURE的值为ARG,或者禁止该特性。
(5)编译时可选的一些包的配置。
一般使用--with-PACKAGE[=ARG]或者--without-PACKAGE来指定包PACKAGE的值或者禁止使用该包。例如使用--with-mpfr =PATH指定mpfr包的目录。
(6)编译时的环境变量。
这些环境变量可能包括编译、汇编、链接等工具以及这些工具运行时的选项值,例如:

./configure CFLAGS="-w -g -O0" --prefix=/opt/paag-gcc --target=paag-linux-gnu --enable-stage1-language=c

其中,CFLAGS="-w -g -O0"就指定了编译标志CLAGS的部分值。表3-1给出了conf?igure脚本中常用环境变量的名称和意义。

3.3.2 编译

执行./conf?igure命令后,就生成了gcc-4.4.0目录下的Makef?ile文件。此时,可以使用make工具来进行整个GCC源代码的编译过程。这个过程的执行异常复杂,为了了解整个编译的详细过程,建议读者将编译的过程重定向到文件中,并结合Makef?ile文件进行仔细研读。例如,可以采用如下命令形式:

[GCC@host1 gcc-4.4.0]$ ./configure CFLAGS="-g -O0" --prefix=/opt/i386 --target= i386-linux-gnu
[GCC@host1 gcc-4.4.0]$ make > make-process 2&>1

GCC源代码编译生成一个在本机运行的编译器时,通常采用一个叫做bootstrapping的技术,即将GCC源代码的编译过程分为多个阶段,通常包括stage1、stage2及stage3三个阶段。这三个阶段的功能分别为:
(1)stage1:使用一个现有的编译器将GCC的源代码编译,生成一个新的编译器new_gcc1;
(2)stage2:使用new_gcc1重新编译GCC的源代码,生成另外一个新的编译器new_gcc2;
(3)stage3:使用new_gcc2重新编译GCC的源代码,生成另外一个新的编译器new_gcc3,并且对new_gcc2和new_gcc3进行比较,如果两者相同,则表示GCC源代码编译成功,否则表示生成的编译器存在bug。
采用上述过程的目的是充分保证编译器的正确性。详细内容可以参考如下文档:
http://stackoverf?low.com/questions/9429491/how-are-gcc-g-bootstrapped
https://gcc.gnu.org/install/build.html
可以通过前面生成的make-process文件中的部分内容验证上述说法。

[GCC@localhost gcc-4.4.0]$ make &> make-process
[GCC@localhost gcc-4.4.0]$ grep stage make-process
[ -f stage_final ] || echo stage3 > stage_final
Configuring stage 1 in host-i686-pc-linux-gnu/intl
Configuring stage 1 in host-i686-pc-linux-gnu/gcc
Configuring stage 1 in host-i686-pc-linux-gnu/libiberty
Configuring stage 1 in host-i686-pc-linux-gnu/zlib
Configuring stage 1 in host-i686-pc-linux-gnu/libcpp
Configuring stage 1 in host-i686-pc-linux-gnu/libdecnumber
Configuring stage 1 in i686-pc-linux-gnu/libgcc
rm -f stage_current
Configuring stage 2 in host-i686-pc-linux-gnu/intl
Configuring stage 2 in host-i686-pc-linux-gnu/gcc
Configuring stage 2 in host-i686-pc-linux-gnu/libiberty
Configuring stage 2 in host-i686-pc-linux-gnu/zlib
Configuring stage 2 in host-i686-pc-linux-gnu/libcpp
Configuring stage 2 in host-i686-pc-linux-gnu/libdecnumber
Configuring stage 2 in i686-pc-linux-gnu/libgcc
rm -f stage_current
Configuring stage 3 in host-i686-pc-linux-gnu/intl
Configuring stage 3 in host-i686-pc-linux-gnu/gcc
Configuring stage 3 in host-i686-pc-linux-gnu/libiberty
Configuring stage 3 in host-i686-pc-linux-gnu/zlib
Configuring stage 3 in host-i686-pc-linux-gnu/libcpp
Configuring stage 3 in host-i686-pc-linux-gnu/libdecnumber
Configuring stage 3 in i686-pc-linux-gnu/libgcc
rm -f stage_current
Comparing stages 2 and 3

以下是各个阶段生成的GCC文件的对比。
使用现有编译器生成的xgcc(即new_gcc1):

[GCC@localhost host-i686-pc-linux-gnu]$ ls stage1-gcc/xgcc -l
-rwxrwxr-x. 1 GCC GCC 499979 Aug 30 15:30 stage1-gcc/xgcc

使用new_gcc1重新编译GCC的源代码,生成另外一个新的编译器xgcc(即new_gcc2):

[GCC@localhost host-i686-pc-linux-gnu]$ ls prev-gcc/xgcc -l
-rwxrwxr-x. 1 GCC GCC 453766 Aug 30 15:44 prev-gcc/xgcc

使用new_gcc2重新编译GCC的源代码,生成另外一个新的编译器xgcc(即new_gcc3):

[GCC@localhost host-i686-pc-linux-gnu]$ ls gcc/xgcc -l
-rwxrwxr-x. 1 GCC GCC 453766 Aug 30 15:49 gcc/xgcc

可以看出,两个阶段生成的编译器gcc/xgcc与prev-gcc/xgcc的大小相同。
另外,还可以使用diff工具对两个编译器目标文件进行对比,从命令的结果可以看出两者是完全相同的,因此,本次GCC源代码的编译是成功的。
[GCC@localhost host-i686-pc-linux-gnu]$ diff gcc/xgcc prev-gcc/xgcc

3.3.3 安装

GCC源代码成功编译后,生成的可执行程序及文档等的安装可以使用如下命令进行:
make install

时间: 2024-11-08 18:57:21

《深入分析GCC 》——3.3 GCC源代码编译的相关文章

CentOS 6.4+nginx-1.4.4+php-5.5.8(php-fpm)+mysql-5.6.15+xcache-3.1.0+memcache-2.2.7源代码编译安装指南

风信网(ithov.com)原创文章:本文将向大家讲解关于CentOS 6.4 X64位系统源代码编译安装nginx-1.4.4+php-5.5.8(php-fpm)+mysql-5.6.15+xcache-3.1.0+memcache-2.2.7的详细过程,希望能帮助大家解决生产环境中的环境配置问题. 安装需要支持的库文件 [root@localhost mysql-5.6.15]# yum install pcre [root@localhost mysql-5.6.15]# yum ins

linux下apache+mysql+php开发环境纯源代码编译搭建

apache|mysql|编译|源代码 记录一下我在fedora core 1下通过源代码编译出来的apache+mysql+php开发环境的全部过程 通常安装一台服务器当然使用rpm是最方便的,不需要考虑太多配置的问题,就可以轻松获得需要的环境了.不过rpm包互相关联的问题也不是这么容易解决. apache,mysql,php这三个应用从源代码编译安装还是比较简单的,配置参数不算复杂,而且没有太多的依赖关系,从源码编译出来的系统也比较稳定一些,方便未来打补丁和升级工作. 编译安装的前提是,系统

题二 源代码编译:拓扑排序

一.题目 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在网易游戏的日常工作中,C++ 是一门常用的语言.面对众多的 C++ 代码,等待源文件编译的漫长时间是个令人糟心的时刻,一直以来大家对此怨声载道.终于有一天,大家找到了你,一位优秀的程序员,请你来帮忙分析一下编译速度的瓶颈. 经过一番调查和研究,你发现一些源代码之间是有依赖关系的.例如,某个源文件 a.cpp 编译链接生成了动态链接库 a.dll,而 b.cpp 编译链接生成的 b.dll 依赖于 a.dll

从源代码编译 Vim 8.0

从源代码编译 Vim 实际上并不那么困难.下面是你所要做的: 1.首先,安装包括 Git 在内的所有必备的库.对于一个 Debian 类的 Linux 发行版,例如 Ubuntu,命令如下: sudo apt-get install libncurses5-dev libgnome2-dev libgnomeui-dev \ libgtk2.0-dev libatk1.0-dev libbonoboui2-dev \ libcairo2-dev libx11-dev libxpm-dev lib

[CLR via C#]1.1 将源代码编译成托管代码

原文:[CLR via C#]1.1 将源代码编译成托管代码 1. 公共语言运行时(Common Language Runtime,CLR)是一种可由多种编程语言使用的"运行时". 2. CLR的核心功能(比如内存管理,程序集加载.安全性.异常处理和线程同步等)可由面向CLR的所有语言使用. 3. 用一个对应的编译器编译源代码之后,结果都是一个托管模块. 4. 托管模块是一个标准的32/64位Microsoft Windows 可移植执行体(PE32/PE32+)文件,它们都需要CLR

c++-网上下载的duilib源代码编译报错,新手求问如何检查。

问题描述 网上下载的duilib源代码编译报错,新手求问如何检查. 下载的是SVN364.先说下错误吧,报错如下: >C:Program Files (x86)Windows Kits8.1Includeumdispex.h(791): error C2011: "ICanHandleException":"struct"类型重定义 1> f:duilibduilib-svn364-20121126svn364duilibUtils/flash11.tl

《OpenStack实战指南》—— 2.2 在Ubuntu上使用源代码编译安装

2.2 在Ubuntu上使用源代码编译安装 对于各个版本的Linux来说,都会制作OpenStack相应的软件包.虽然在2.1节中介绍了二进制包安装,但是在这里笔者还是会讲一下源代码安装OpenStack基本组件的过程,因为从学习的角度来说,通过源代码安装OpenStack各个组件的过程,可以使读者对OpenStack的框架和各个组件的作用有一个比使用二进制安装更全面的了解.另一个好处是,二进制包的发布会滞后于源代码,如果想在第一时间尝试一些最新的功能或修复Bug后的版本,源代码安装是个不错的选

自己动手写操作系统源代码编译,链接错误,求解。

问题描述 自己动手写操作系统源代码编译,链接错误,求解. 自己动手写操作系统源码(D:Tinixchapter5h),编译结果如下: $ MAKE ld -s -Ttext 0x30400 -o kernel.bin kernel/start.o lib/string.o lib/klib.o kernel/kernel.o kernel/start.o:start.c:(.text+0xe): undefined reference to disp_str' kernel/start.o:st

《深入理解Android:Telephony原理剖析与最佳实践》一第2章 搭建Android源代码编译环境

第2章 搭建Android源代码编译环境 第1章介绍了Android以及其Telephony功能模块的基本结构,在本章中将带着读者去搭建Android编译环境.即使你已经能够在自己计算机上成功编译Android源代码了,也希望你能阅读本章内容,因为本章不乏一些技巧的总结和Android相关实用工具使用方法的介绍. Android的编译环境作为深入学习Android的基础,不可缺失,能够成功下载Android源代码并编译成功,对深入学习Android是非常关键和重要的一步:Android环境搭建比