标题:
GNU Compiler Collection 基本操作更新
[打印本页]
作者:
look_w
时间:
2017-11-18 21:37
标题:
GNU Compiler Collection 基本操作更新
警告选项
GCC 在报告错误消息时可以使用不同的粒度。在 GCC 手册中的 3.8 节列出了警告和错误选项。)除了能够打开或关闭每种类型的警告信息之外, 还有几个元选项来控制警告和错误消息的类型。这样可以让编译器进行一些严格的检查。
-fsyntax-only 选项会通知编译器只关心那些真正不符合语法规发的地方。这是编译器最松散的一种状态,与 -pedantic 选项正好相反。
-pedantic 选项会产生选定的 ISO 标准所希望的所有警告信息。这个标记还会禁用扩展,__keywords__ 和以 __extension__ 标识符开始的表达式除外。-pedantic-errors 选项会导致编译器编译器在碰到每个警告信息时就停止,仿佛遇到的是一个错误。
-Wall 现象会使用很多警告信息,但是只有警告信息,没有其他信息。-Wall 究竟会产生哪些消息是一个经验问题。正如在 GCC 手册中介绍的一样,这个选项 " 会启用所有有关那些某些用户认为存在问题而且很容易避免的结构的警告信息 " 。-Wextra 选项则会通知编译器要报告所有其他认为可能较少出现问题的警告消息。在 GCC 手册的 3.8 节中,可以看到这些标记可以捕捉到的所有警告信息的完整清单。
如果一个标准可以同时使用 -std= 选项和 -pedantic 选项来测试代码是否遵守某个标准,那会很有吸引力。然而,这在实践中却并不怎样。虽然 -pedantic 选项实际上会对标准所希望产生警告的每个结构都产生警告信息,但是它并没有解决标准中的所有情况,因此它会替换成实际的标准遵守测试。
调试选项
交互式调试程序可以极大地加速代码中问题的分析。GNU Project Debugger,或称为 gdb,可以在程序中任何给定的地点停止,跟踪程序的执行过程,检查程序执行过程中到底发生了什么;如果程序没有正常结束,还可以修改程序的执行过程。
为了在 Linux on POWER 上使用 gdb,必须使用调试选项来编译代码。在使用 -g 或 -ggdb 选项编译代码时,会产生 DWARF 和 DWARF2 格式的信息。-pedantic 标记会产生 DWARF 信息供 gdb 使用。但是与大部分调试器不同,gdb 可以同时使用 -g 和 -O 标记(基本优化标记)。这是 gdb 特有的一个特性,在其他很多调试器中都没有这个特性,因为经过优化之后,代码的组织和执行都会发生变化。然而您也要有所准备,因为同时使用 -O 和 -g 会可能对代码重新进行调整,这在使用调试器时会受到影响。如果给 GCC 传递 -ggdb 选项,GDB 就可以使用意义更加丰富的 DWARF 2 格式。这同时会启用 gdb 的扩展。
-g 和 -ggbd 选项都可以接受一个级别参数(例如,-ggdb1 标识级别 1)。从直观上来看,这个级别越高(一共有 3 个),调试器中可以使用的调试信息就越多。这是一个折中:调试信息越多,程序就越大,执行速度也就越慢。gcc 还有很多标记可以用来进行配置。这包括 gprof 和 gcov 用来搜集数据的一些选项,以及用来报告内存使用情况、优化信息的标记,等等。很多这种选项通常都是用来调试程序的,而不是用来编译代码的。最后一组调试标记是有关编译环境的。诸如 -print-file-name= 之类的选项用来验证所提供的编译环境是不是我们所希望的环境。
完整的调试标记,请参阅 GCC 手册的 3.9 节。
优化选项
GCC 为 C/C++ 代码和所支持的其他语言提供了一个后台优化器。由于 Linux on POWER 是一个性能很高的平台,因此对于开发人员来说,理解这个优化器的操作非常重要。注意,并不是所有的优化程序都被详细记录,而是只有那些可以使用命令行选项调用的程序会有被记录。此处,介绍的这些选现并不是从它们性能的角度进行讨论的,而是从它们的移植和调试角度进行讨论的。完整的优化选项,请参考 GCC 手册的 3.10 节。
分组优化标记可以让编译器使用一个标记来选择一组优化选项。它们用来对代码的性能或大小进行不同级别的优化。-O 或 -O1 标记是第一个组优化标记,它包括包括了一些不用多少编译时间就可以实现的优化步骤。-O2 实现的是那些可以用来提高性能但却不会增加程序大小的优化;比较 -O3 与 -O2,针对性能进一步进行优化,而不管是否会影响程序的大小。-Os 是对程序的大小进行优化,即使会影响程序的性能也在所不惜。注意,并没有一个分组选项可以选择使用编译器中所有可用的性能优化选项。还有一个值得注意的事项是,对于 GCC 来说,-O 与 -O1 是完全相同的。但对于其他一些编译器来说,情况并非如此,这些编辑器包括 IBM XL C/C++ 编译器,该编辑器也可以在 Linux on POWER 上使用。
注意,有些选项对于编译器来说是明智的,因为它们会影响到开发的各个方面,例如调试。-fomit-frame-pointer 就是一个这种选项,在所有的 -O 级别中都会启用这个选项,它会在不需要的地方删除 frame 指针。这个选项可以提高性能,但是这个标记的规范却并不担保实现了优化。在 -fomit-frame-pointer 的例子中,这是因为 POWER 平台上的堆栈指针就是一个 frame 指针,在使用 alloca() 机制在堆栈中动态分配内存时更是如此。在这些情况中,frame 指针必须保留,以便提供反向的跟踪。这是一个启发式优化有害的例子,因此编译器会将其忽略。
POWER 架构中有一个分支计数寄存器,GCC 有一个利用这种特性的选项:-fbranch-count-reg。该特性利用了 POWER 架构可以对计数寄存器进行消耗和分支的能力,而不是采用消耗(和 0 作比较)和有条件的分支。在从 SPARC 往 Linux on POWER 上移植程序时,要确认启用了这个选项,因为 SPARC 并不支持这种特性。如果启用了 -O2,那么 -fbranch-count-reg 标记默认情况下是启用的。再次重申,在某些上下文中,编译器是不会应用这种优化的。在这种情况中,不包含函数调用的循环可以从这个选项中获益良多,但是在函数调用之前复制计数寄存器的内容所带来的负载可能会超过使用计数寄存器操作所带来的优点。
预处理选项
GNU 的预处理器是与编译器一起对源文件进行处理,它们将源程序中的文本转换成一些指令用来进行编译。GNU 预处理器是在 GCC 驱动器的控制之下自动进行操作的,GCC 驱动器中有几个选项可以用来引导预处理器的行为。
与 GCC 所驱动的其他工具链工具一样,预处理器可以使用 -Wp 选项向预处理器传递预定义的选项,或者使用 -Xpreprocessor 选项向预处理器显式地传递外部指定的选项。Linux on POWER 没有 GCC 驱动器标记不能使用的预处理器选项。也就是说,我们没有什么理由去使用 -Xpreprocessor 标记,而不使用 -Wp 标记。
-undef 选项可以取消 GCC 或目标平台所特有的宏定义。在计划进行移植时,这非常有用,因为它可以帮助确定移植的问题。
-M 选项通常也非常有用,因为它可以用来显示源文件所需要的所有依赖关系。这种依赖关系乐意用来检查源代码和目标平台的可用性。
-I 选项用来包含要搜索的头文件所在的目录。如果一个依赖关系是使用 -I 选项直接指定的,并且这个包含的路径没有成功,那么需要确保系统中已经安装了所有的更新包,并应用了所有的服务包。在较低版本的 Linux on POWER 上,安装程序有些问题,没有完全安装部分系统库和头文件。具体地说,Red Hat Enterprise Linux Version 3 上 64 位的标准和兼容库就存在这个问题。RHEL3 的所有问题在 RHEL3 Update 3 中已经得以修正。
汇编程序选项
与预处理器类似,GNU 汇编程序也可以接受 GCC 能够识别和不能识别的一些选项:它们分别是 -Wa 和 -Xassembler 标记。
这两个选项在后文的一节中会深入进行介绍。
链接器选项
链接器也可以使用类似于 -Wa 和 -Xassembler 的选项:-Wl 和 -Xlinker。然而,与汇编程序选项不同,GCC 驱动器可以接受一些直接对链接器行为产生影响的选项。
Linux on POWER 上有两种编译器:GCC 和 XL C/C++ for Linux on POWER。由于这两种编译器都使用了 GNU 工具链,因此它们生成的对象是完全兼容的。对象名的清单可以作为参数传递给 GCC 驱动器,这会告诉链接器在链接成可执行文件时包含这个对象文件。在将多个编译器产生的对象链接为可执行程序时,这个选项非常有用。例如,可以考虑这样一个应用程序:它有很多进程组件,其中一些进程需要考虑可移植性的问题。那些对性能至关重要的代码可以使用 XL C/C++ 进行编译,以便获得更好的性能;其余的代码可以使用 GCC 进行编译。这种方法最大限度地利用了编译器的性能、GNU 工具链的灵活性以及可以将这两个编译器编译出来的对象链接成可执行程序的优点。
GCC 驱动器也可以接受一些参数,指定在链接时包含哪些库。-l 选项可以接受库的名称,可以直接使用,也可以作为遵守 POSIX 规范的一个单独参数。这个参数的排序规则非常重要。库是按照指定的顺序进行搜索的。因此要确保其他库或对象所依赖的库要首先列出。
虽然从理论上来说,将 32 位对象和 64 位对象链接在一起是可行的,但是目前 GNU 工具链还没有实现这种功能。从架构上来说,存在一些原因可以解释为什么没有实现这种功能。在 POWER 平台上,将整个应用程序都编译成 64 位的并不会降低程序的性能。
代码生成选项
有些与机器平台无关的选项可以影响生成代码的方式,在 Linux on POWER 可能会有一些特殊的影响。在将程序从 Linux on Intel 移植到 Linux on POWER 时,一个常见的变化就是对位置无关的代码的考虑。-fpic 选项用来生成与位置无关的代码,用来在 GCC 中使用共享库使用。在很多平台上,这个选项是必须指定的,但是在 POWER 架构上,这要取决于到底是使用 32 位模式还是采用 64 位模式来编译应用程序。在 64 位模式中,所有的对象都是与位置无关的;而在 32 位模式中,您必须指定 -fpic 选项。Makefile 和编译脚本在为 Linux on POWER 配置编译标记时,就应该考虑这个问题。
堆栈的反向跟踪(stack backtrace)可以用来研究程序究竟是如何执行的。如果程序出错,那么反向跟踪可以提供一些内幕信息,说明究竟是哪个函数调用应该对这个问题负责。即使程序执行成功了,反向调用也可以用来研究程序是否是按照程序员所想象得那样执行。反向跟踪依赖于构成程序的对象中的 frame 指针。
为对象生成 frame 指针,既不需要 32 位的 ABI for Linux on POWER,也不需要 64 位的 ABI for Linux on POWER。这会使得调试变得更为复杂,尤其是建立反向跟
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0