gcc命令⼤全
⼀、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 的数学函数库。
eg:
假定有⼀个程序名为 test.c 的C语⾔源代码⽂件,要⽣成⼀个可执⾏⽂件。
#include <stdio.h>
int main(void)
{
printf("Hello world/n");
return0;
}
最简单的办法: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
对于稍微复杂的情况,⽐如有多个源代码⽂件、需要链接库或有其他⽐较特别的要求,就要给定适当的调⽤选项参数:
eg:
整个源代码程序由两个⽂件 testmain.c 和 testsub.c 组成,程序中使⽤了系统提供的数学库(所有与浮点相关的数学运算都必须使⽤数学库)。
gcc testmain.c testsub.c -lm -o test
其中,-lm 表⽰链接系统的数学库 libm.a 。
说明:
在编译⼀个包含许多源⽂件的⼯程时,若只⽤⼀条gcc命令来完成编译是⾮常浪费时间的。假如项⽬中有100个源⽂件需要编译,并且每个源⽂件中都包含⼀万⾏代码,如果像上⾯那样仅⽤⼀条gcc命令来
完成编译⼯作,那么gcc需要将每个源⽂件都重新编译⼀遍,然后再全部链接起来。很显然,这样浪费的时间相当多,尤其是当⽤户只是修改了其中某个⽂件的时候,完全没有必要将每个⽂件都重新编译⼀遍,因为很多已经⽣成的⽬标⽂件是不会发⽣改变的。要解决这个问题,需要借助像make这样的⼯具(make在其他⽂章会有详解)。
⼆、警告提⽰功能选项
gcc包含完整的出错检查和警告提⽰功能,它们可以帮助Linux程序员写出更加专业的代码。
(1)-pedantic 选项
当gcc在编译不符合ANSI/ISO C 语⾔标准的源代码时,将产⽣相应的警告信息。
(2)-Wall 选项
linux下gcc编译的四个步骤除了 -pedantic 之外,gcc 还有⼀些其他编译选项,也能够产⽣有⽤的警告信息。这些选项⼤多以 -W
开头。其中最有价值的当数 -Wall 了,使⽤它能够使 gcc 产⽣尽可能多的警告信息。
gcc 给出的警告信息虽然从严格意义上说不能算作错误,但却和可能成为错误来源。⼀个优秀的程序员应该尽量避免产⽣警告信息,使⾃⼰的代码始终保持简洁、优美和健壮的特性。
(3)-Werror 选项
在处理警告⽅⾯,另⼀个常⽤的编译选项是 -Werror。它要求 gcc 将所有的警告当成错误进⾏处理,这在使⽤⾃动编译⼯具(如 Make 等)时⾮常有⽤。如果编译时带上 -Werror 选项,那么 gcc 会在所有产⽣警告的地⽅停⽌编译,迫使程序员对⾃⼰的代码进⾏修改。只有当相应的警告信息消除时,才可能将编译过程继续朝前推进。
三、库操作选项
在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 进⾏处理时,会⾃动去链接名为 的⽂件。
(4) -static
Linux下的库⽂件分为两⼤类,分别是:动态链接库(通常以 .so 结尾)和静态链接库(通常以 .a 结尾)。
两者的差别仅在程序执⾏时所需的代码是在运⾏时动态加载的,还是在编译时静态加载的。
默认情况下,gcc 在链接时优先使⽤动态链接库,只有当动态链接库不存在时才考虑使⽤静态链接库。
如果需要的话,可以在编译时加上 -static 选项,强制使⽤静态链接库。
(5) -shared
⽣成⼀个共享的⽬标⽂件,它能够与其他的⽬标⼀起链接⽣成⼀个可执⾏的⽂件。
四、调试选项
对于Linux程序员来讲,gdb(GNU Debugger)通过与 gcc 的配合使⽤,为基于Linux的软件开发提供了⼀个完善的调试环境。常⽤的有:
(1) -g 和 -ggdb
默认情况下,gcc 在编译时不会将调试符号插⼊到⽣成的⼆进制代码中,因为这样会增加可执⾏⽂件的⼤⼩。如果需要在编译时⽣成调试符号信息,可以使⽤ gcc 的 -g 或 -ggdb 选项。
gcc 在产⽣调试符号时,同样采⽤了分级的思路,开发⼈员可以通过在 -g 选项后附加数字1、2、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 中间⽂件,供⽤户查询调试。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论