gcc的使用简介与命令行参数说明

(一) gcc的基本用法
(二) 警告提示功能选项
(三) 库操做选项
(四) 调试选项
(五) 交叉编译选项
linux



(一) gcc的基本用法
使用gcc编译器时,必须给出一系列必要的调用参数和文件名称。不一样参数的前后顺序对执行结果没有影响,只有在使用同类参数时的前后顺序才须要考虑。若是使用了多个 -L 的参数来定义库目录,gcc会根据多个 -L 参数的前后顺序来执行相应的库目录。
由于不少gcc参数都由多个字母组成,因此gcc参数不支持单字母的组合,Linux中常被叫短参数(short options),如 -dr 与 -d -r 的含义不同。gcc编译器的调用参数大约有100多个,其中多数参数咱们可能根本就用不到,这里只介绍其中最基本、最经常使用的参数。

gcc最基本的用法是:gcc [options] [filenames]
其中,options就是编译器所须要的参数,filenames给出相关的文件名称,最经常使用的有如下参数:

-c    
只编译,不连接成为可执行文件。编译器只是由输入的 .c 等源代码文件生成 .o 为后缀的目标文件,一般用于编译不包含主程序的子程序文件。
-o output_filename    
肯定输出文件的名称为output_filename。同时这个名称不能和源文件同名。若是不给出这个选项,gcc就给出默认的可执行文件 a.out 。
-g
产生符号调试工具(GNU的 gdb)所必要的符号信息。想要对源代码进行调试,就必须加入这个选项。
-O
对程序进行优化编译、连接。采用这个选项,整个源代码会在编译、连接过程当中进行优化处理,这样产生的可执行文件的执行效率能够提升,可是编译、连接的速度就相应地要慢一些,并且对执行文件的调试会产生必定的影响,形成一些执行效果与对应源文件代码不一致等一些使人“困惑”的状况。所以,通常在编译输出软件发行版时使用此选项
-O2
比 -O 更好的优化编译、连接。固然整个编译连接过程会更慢。
-Idirname
将 dirname 所指出的目录加入到程序头文件目录列表中,是在预编译过程当中使用的参数。
说明:
C程序中的头文件包含两种状况:
#include <stdio.h>
#include "stdio.h"
其中,使用尖括号(<>),预处理程序 cpp 在系统默认包含文件目录(如/usr/include)中搜索相应的文件;使用双引号,预处理程序 cpp 首先在当前目录中搜寻头文件,若是没有找到,就到指定的 dirname 目录中去寻找。
在程序设计中,若是须要的这种包含文件分别分布在不一样的目录中,就须要逐个使用 -I 选项给出搜索路径
-Ldirname
将dirname所指出的目录加入到程序函数库文件的目录列表中,是在连接过程当中使用的参数。在默认状态下,连接程序 ld 在系统默认路径中(如 /usr/lib)寻找所须要的库文件。这个选项告诉连接程序,首先到 -L 指定的目录中去寻找,而后到系统默认路径中寻找;若是函数库存放在多个目录下,就须要依次使用这个选项,给出相应的存放目录。
-lname
连接时装载名为 libname.a 的函数库。该函数库位于系统默认的目录或者由 -L 选项肯定的目录下。例如,-lm 表示连接名为 libm.a 的数学函数库。

例子:假定有一个程序名为 test.c 的C语言源代码文件,要生成一个可执行文件。
#include <stdio.h>
int main(void)
{
    printf("Hello world/n");
    return 0;
}
最简单的办法:gcc test.c -o test
首先,gcc须要调用预处理程序 cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,gcc调用 ccl 和 as,将处理后的源代码编译成目标代码;最后,gcc调用连接程序 ld,把生成的目标代码连接成一个可执行程序。所以,默认状况下,预编译、编译连接一次完成。

编译过程的分步执行:
为了更好地理解gcc的工做过程,咱们可让在gcc工做的4个阶段中的任何一个阶段中中止下来。相关的参数有:
-E
预编译后停下来,生成后缀为 .i 的预编译文件
-c
编译后停下来,生成后缀为 .o 的目标文件
-S
汇编后停下来,生成后缀为 .s 的汇编源文件

第一步:进行预编译,使用 -E 参数
gcc -E test.c -o test.i
查看 test.i 文件中的内容,会发现 stdio.h 的内容确实都插到文件里去了,而其余应当被预处理的宏定义也都作了相应的处理。
第二步:将 test.i 编译为目标代码,使用 -c 参数
gcc -c test.c -o test.o
第三步:生成汇编源文件
gcc -S test.c -o test.s
第四步:将生成的目标文件连接成可执行文件
gcc test.o - o test

对于稍微复杂的状况,好比有多个源代码文件、须要连接库或有其余比较特别的要求,就要给定适当的调用选项参数。

例子:整个源代码程序由两个文件 testmain.c 和 testsub.c 组成,程序中使用了系统提供的数学库(全部与浮点相关的数学运算都必须使用数学库)。
gcc testmain.c testsub.c -lm -o test
其中,-lm 表示连接系统的数学库 libm.a 

说明:
在编译一个包含许多源文件的工程时,若只用一条gcc命令来完成编译是很是浪费时间的。假如项目中有100个源文件须要编译,而且每一个源文件中都包含一万行代码,若是像上面那样仅用一条gcc命令来完成编译工做,那么gcc须要将每一个源文件都从新编译一遍,而后再所有连接起来。很显然,这样浪费的时间至关多,尤为是当用户只是修改了其中某个文件的时候,彻底没有必要将每一个文件都从新编译一遍,由于不少已经生成的目标文件是不会发生改变的。要解决这个问题,须要借助像make这样的工具。

(二) 警告提示功能选项
gcc包含完整的出错检查和警告提示功能,它们能够帮助Linux程序员写出更加专业的代码。
(1) -pedantic 选项
当gcc在编译不符合ANSI/ISO C 语言标准的源代码时,将产生相应的警告信息。程序员

 

 

[cpp]  view plain  copy
 
 print?
  1. #include <stdio.h>  
  2.   
  3.  void main(void)  
  4.  {  
  5.      long long int var = 1;  
  6.      printf("It is not standard C code!/n");  
  7.  }  

 

pic

 

它有如下问题:
> main 函数的返回值被声明为 void,但实际上应该是 int。
> 使用了 GNU 语法扩展,即便用 long long 来声明64位整数,不符合 ANSI/ISO C 语言标准。
> main 函数在终止前没有调用 return 语句。

(2) -Wall 选项
除了 -pedantic 以外,gcc 还有一些其余编译选项,也可以产生有用的警告信息。这些选项大多以 -W 开头。其中最有价值的当数 -Wall 了,使用它可以使 gcc 产生尽量多的警告信息。编程

pic

 

gcc 给出的警告信息虽然从严格意义上说不能算做错误,但却和可能成为错误来源。一个优秀的程序员应该尽可能避免产生警告信息,使本身的代码始终保持简洁、优美和健壮的特性。
建议:gcc 给出的警告信息是颇有价值的,它们不只能够帮助程序员写出更加健壮的程序,并且仍是跟踪和调试程序的有力工具。建议在用 gcc 编译源代码时始终带上 -Wall 选项,并把它逐渐培养成一种习惯,这对找出常见的隐式编程错误颇有帮助。

(3) -Werror 选项
在处理警告方面,另外一个经常使用的编译选项是 -Werror。它要求 gcc 将全部的警告当成错误进行处理,这在使用自动编译工具(如 Make 等)时很是有用。若是编译时带上 -Werror 选项,那么 gcc 会在全部产生警告的地方中止编译,迫使程序员对本身的代码进行修改。只有当相应的警告信息消除时,才可能将编译过程继续朝前推动。函数

pic

 

(4) -Wcast-align 选项
当源程序中地址不须要对齐的指针指向一个地址须要对齐的变量地址时,则产生一个警告。例如,char * 指向一个 int * 地址,而一般在机器中 int 变量类型是须要地址能被2或4整除的对齐地址。

(5) 其余经常使用选项
-v                            输出 gcc 工做的详细过程
--target-help       显示目前所用的gcc支持CPU类型
-Q                           显示编译过程的统计数据和每个函数名

(三) 库操做选项
Linux下开发软件时,彻底不使用第三方函数库的状况是比较少见的,一般来说都须要借助一个或多个函数库的支持才可以完成相应的功能。
从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(.so 或 .a)的集合。虽然Linux下的大多数函数都默认将头文件放到 /usr/include/ 目录下,而库文件则放到 /usr/lib/ 目录下,但并非全部的状况都是这样。正因如此,gcc 在编译时必须有本身的办法来查找所须要的头文件和库文件。经常使用的方法有:
(1) -I 
能够向 gcc 的头文件搜索路径中添加新的目录。
(2) -L 
若是使用了不在标准位置的库文件,那么能够经过 -L 选项向 gcc 的库文件搜索路径中添加新的目录。
(3) -l 
Linux下的库文件在命名时有一个约定,就是应该以 lib 这3个字母开头,因为全部的库文件都遵循了一样的规范,所以在用 -l 选项指定连接的库文件名时能够省去 lib 这3个字母。例如,gcc 在对 -lfoo 进行处理时,会自动去连接名为 libfoo.so 的文件。
(4) -static
Linux下的库文件分为两大类,分别是:动态连接库(一般以 .so 结尾)和静态连接库(一般以 .a 结尾)。
二者的差异仅在程序执行时所需的代码是在运行时动态加载的,仍是在编译时静态加载的。
默认状况下,gcc 在连接时优先使用动态连接库,只有当动态连接库不存在时才考虑使用静态连接库。
若是须要的话,能够在编译时加上 -static 选项,强制使用静态连接库。
(5) -shared
生成一个共享的目标文件,它可以与其余的目标一块儿连接生成一个可执行的文件。
 
(四) 调试选项
对于Linux程序员来说,gdb(GNU Debugger)经过与 gcc 的配合使用,为基于Linux的软件开发提供了一个完善的调试环境。经常使用的有:
(1) -g 和 -ggdb
默认状况下,gcc 在编译时不会将调试符号插入到生成的二进制代码中,由于这样会增长可执行文件的大小。若是须要在编译时生成调试符号信息,可使用 gcc 的 -g 或 -ggdb 选项。
gcc 在产生调试符号时,一样采用了分级的思路,开发人员能够经过在 -g 选项后附加数字一、二、3指定在代码中加入调试信息的多少。默认的级别是2(-g2),此时产生的调试信息包括:扩展的符号表、行号、局部或外部变量信息。
级别3(-g3)包含级别2中的全部调试信息以及源代码中定义的宏。
级别1(-g1)不包含局部变量和与行号有关的调试信息,所以只可以用于回溯跟踪和堆栈转储。
回溯追踪:指的是监视程序在运行过程当中函数调用历史。
堆栈转储:则是一种以原始的十六进制格式保存程序执行环境的方法。

注意:使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增长,同时增长程序在执行时的开销,所以,调试选项一般仅在软件的开发和调试阶段使用。

(2) -p 和 -pg
会将剖析(Profiling)信息加入到最终生成的二进制代码中。剖析信息对于找出程序的性能瓶颈颇有帮助,是协助Linux程序员开发出高性能程序的有力工具。

(3) -save-temps
保存编译过程当中生成的一些列中间文件。
# gcc test.c -o test -save-temps
除了生成执行文件test以外,还保存了test.i 和 test.s 中间文件,供用户查询调试。

(五) 交叉编译选项
一般状况下使用 gcc 编译的目标代码都与使用的机器是一致的,但 gcc 也支持交叉编译的功能,可以编译其余不一样CPU的目标代码
使用 gcc 开发嵌入式系统,咱们几乎都是以通用的PC机(X86)平台来作宿主机,经过 gcc 的交叉编译功能对其余嵌入式CPU的开发任务。
(具体的选项设置,此处省略)工具

相关文章
相关标签/搜索