首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

GNU Compiler Collection 基本操作

GNU Compiler Collection 基本操作

GNU Compiler Collection从历史传统上来说,GCC 是代表 GNU C Compiler,但是现在它代表 GNU Compiler Collection。GCC 是用于                C、C++、Objective-C、Java™、Fortran 和 Ada 编程语言的一个编译器集。不过本文的讨论仅仅局限于 C 和 C++                编译器,尤其是那些 GCC 的操作和选项、特定于 POWER 架构的 GCC 特性操作和受 GCC 支持的最新特性,这些特性是随 Linux for                POWER 架构的两个领先发行版本(Red Hat Enterprise Server AS 和 SUSE LINUX Enterprise                Server)一起打包的。
GCC 的基本操作GCC 的基本操作驱动着预处理、编译、汇编和链接的过程。传递给 GCC                的大部分选项实际上都会被重定向给工具链中的其他组件。有些选项,例如平台的选择、调试和优化标记,会为编译器和其他组件同时提供参数。
输入选项
编译器必须知道要处理的是哪种类型的输入数据。例如,C 源程序文件的处理就与 C++                文件不同。对于编译器来说,有一个基本的隐式选项:源程序文件的扩展名。该选项将决定调用哪一个 GCC 编译器。例如,file.c 调用的是 C                编译器,而 foo.C 或 foo.cxx 则会调用 C++ 编译器。在 GCC 手册中列出了可接收源代码文件的扩展名的完整列表。
下图展示了 GNU Toolchain 生成可执行程序或共享对象所应采取的步骤。GCC 驱动器通过接受一些选项对整个 toolchain                间接进行控制。
图 1. 生成可执行程序或共享对象的步骤输出选项
编译器还必须知道用户期望获得哪种类型的输出。GCC                驱动器可以为整个工具链的其他部分产生一些指令,从而生成最终的可执行程序,或者在生成一些中间文件时就停止。您可以使用源程序的文件扩展名或命令行选项来控制编译器的输出。
表 1 对输出文件的选项进行了总结。
表 1. 输出文件的选项标记操作输出格式-c汇编,但不链接.o 文件-S编译,但不汇编.s                            文件-E预处理,但不编译对                            .c 文件进行预处理后的结果
例如,下面的命令可以对源文件 hello.c 进行预处理和编译,生成 hello.s 文件:
1
$ gcc -S hello.c




所生成的文件 hello.s 就已经可以进行汇编生成对象文件了。
另外一组输出现象影响的是编译器的输出信息,而不是输出文件的格式。-v                选项会显示编译过程的详细信息,-###                选项的作用是显示这些详细信息,但是并不执行这些命令。后面这个选项在创建编译脚本时尤其有用。
Dialect 和标准选项
正如前面介绍的一样,GCC                可以为很多种语言编译二进制文件。这些语言都有一些特定变体,即方言,这些变体被概括为特殊的语言约定。GCC                可以接受一些选项来指定编译器所使用的方言。这包括标准选项,以及对标准限定进行修改的更具体的标记。GCC 支持 1990 年发布的 ANSI C                Standard,并支持 1995 年所添加的扩展,以及部分支持 C99 修正标准。
-ansi 和 -std                标记可以用来对编译器强制施加一些限制。-ansi 标记会禁用 GNU 的扩展,例如 inline 和                asm。注意其他的 GNU 关键字,例如 __inline__ 和                __asm__ 依然可以继续使用,不过这会破坏对语言标准规范的遵守。-ansi 选项还会禁止在                C 语言中使用 C++ 风格的注释。
-std= 选项可以指定标准等级或 GNU 对该标准的扩展等级。这些选项在下表中进行了总结。可以在 GCC 手册的 3.4                节中看到所有可用规范的完整列表。
表 2. 标准和标准扩展选项-std= 标记标准或标准扩展c89 或 iso9899:1990 ISO C90(与 -ansi                            相同)iso9899:199409 ISO C90,1994 amendmentc99, c9x, iso9899:1999, or iso9899:199xISO C99                            (并不完全支持)gnu89ISO C90 with GNU extensions(默认)gnu99 或 gnu9x ISO C99 with GNU extensionsc++98 Amended 1998 ISO C++ standardgnu++98Amended 1998 ISO C++ standard, with GNU                            extensions (默认)
更新标准的特性如果与以前的 C 标准并不冲突,那就可以使用。即使不指定 -std= 标记,情况也是如此。例如,即使不指定                -std=c99,也可以使用                __restrict__ ,条件是它不会与所指定的旧标准冲突。
有一些更加具体的标记,例如                -fno-asm,可以用来强制是否遵从某种标准。这种类型的标记提供了一些强制关键字、通用有符号数据类型,并可以显示数据元素是保存在二进制文件的什么地方,以及其他一些信息。关于                C 和 C++ 的 dialect 选项的完整信息,请分别参阅 GCC 手册的 3.4 节和 3.5 节。
除了 ANSI 标准之外,GCC 还支持 GNU 对 C 和 C++ 语言的一些扩展,这些扩展在 ANSI                标准中并不支持。在本文中并没有对这些扩展过多进行讨论,但是如果开发人员希望自己的代码可以在其他 GNU                平台之间可以很好地移植,我们强烈建议开发人员要了解这些区别。在下面的                 中给出了一个主要的扩展,这是因为这种用法非常常见,而且这是一个很好的可移植扩展的例子。
GNU 扩展可以使用前后的双下划线进行标记。例如,__asm__ 就是 GNU 对 asm                的扩展,它可以在规范中允许指令的操作数使用 C 表达式。
现在请考虑下面这个例子,它来自于 Linux 内核的源代码,使用了 GNU 的扩展:
清单 1. GNU                扩展
1
2
3
4
5
6
7
8
9
10
11
12
13
static __inline__ void atomic_sub(int a, atomic_t *v)
{
        int t;
        __asm__ __volatile__(
"1:     lwarx   %0,0,%3         # atomic_sub\n\
        subf    %0,%2,%0\n"
        PPC405_ERR77(0,%3)
"       stwcx.  %0,0,%3 \n\
        bne-    1b"
        : "=&r" (t), "=m" (v->counter)
        : "r" (a), "r" (&v->counter), "m" (v->counter)
        : "cc");   
}




注意,在这个例子中使用了 inline、asm 和 volatile                关键字的另外一种可替代形式:前后都使用了双下划线。
__GNUC__ 宏定义通常是为 GCC 进行预定义的,可以用来检查在编译代码时是否使用了对 GNU                扩展的支持。您可以认为这就像是在询问某一个编译器是否是 GCC 一样。我们建议您使用 GNU 的扩展关键字来检查是否存在 GNU                扩展,从而保证与其他编译器的可移植能力。例如:
1
2
3
#ifndef __GNUC__
#define __asm__ asm
#endif




这会检查是否存在 GNU 的扩展,如果不存在,就将后面的代码中会出现的一些关键字定义为其他编译器可以识别的关键字。
当使用 pedantic 警告信息调用 GNU 编译器时,所有的 GNU 扩展都会被报告为警告信息。通过在所有使用 GNU                扩展关键字的表达式之前都加上 __extension__ 关键字,可以解决这个问题。
记住,这是 GNU                扩展及其用法的一个例子。其他编译器也有很多特性,其中有一些都是类似的非标准特性。严谨的开发计划包括对这些扩展在可移植性和性能影响方面的理解。在                GCC 手册中完整介绍了所有的可用扩展。
返回列表