gcc/g++命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点。现在很多程序员都应用GCC,怎样才能更好的应用GCC。目前,GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序,可根据需要选择安装支持的语言。
简单讲,编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。举个例子:当我们使用C语言写了一段程序,想被运算机器执行(电脑或其它嵌入式设备等等),编译器就是负责把这一段程序转换成可以指定机器上执行的指令。
gcc编译主要工作流程有四个部分:预处理(preprocessing),编译(compilation),汇编(assembly),链接(linking),当前网络上还有其它的表现形式,如:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables),其实原理都一样,只是后面的更方便理解。关于编译原理有详情说明。
语法:gcc (选项)(参数:文件)
写一个hello.c的程序
#include
int main(){
printf("hello world!");
return 0;
}
1、无选项编译链接
$ gcc hello.c
hello.c预处理、编译、汇编并链接形成可执行文件。这里未指定输出文件,在Linux上默认输出为a.out,在window环境中编译默认为a.exe。
$ ls
a.exe hello.c
查看生成a.exe执行文件
$ ./a.exe
hello world!
执行a.exe,输出结果
2、选项 -o(理解成output),对生成的目标进行重命名,linux下为hello.out,windows下为hello.exe
$ gcc -o hello hello.c
$ ls
a.exe hello.c hello.exe
3、选项 -E,把源代码预处理输出为hello.i文件,详见下一篇
$ gcc -E hello.c -o hello.i
$ ls
a.exe hello.c hello.exe hello.i
与cpp hello.c > hello.i命令功能一致。
4、选项 -S,把预处理输出的文件hello.i汇编成hello.s文件
$ gcc -S hello.i
$ ls
a.exe hello.c hello.exe hello.i hello.s
查看汇编后hello.s的内容
.file "hello.c"
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "hello world!\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call printf
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (GNU) 7.3.0"
.def printf; .scl 2; .type 32; .endef
5、选项 -c,把汇编成hello.s文件编译输出为hello.o文件,输出文件为二进制目标文件。
$ gcc -c hello.s
$ ls
a.exe hello.c hello.exe hello.i hello.o hello.s
与as hello.s -o hello.o命令功能一致。
在IDA工具中查看hello.o文件
6、无选项链接,把hello.o目标文件链接成最终可执行文件hello1.exe,其实是调用ld命令进行链接。
$ gcc hello.o -o hello1
$ ls -l
总用量 394
-rwxrwxr-x+ 1 Administrator None 155707 八月 3 15:31 a.exe
-rwxrwx---+ 1 Administrators None 68 八月 3 15:21 hello.c
-rwxrwxr-x+ 1 Administrator None 34373 八月 3 16:48 hello.exe
-rw-rw-r--+ 1 Administrator None 34373 八月 3 16:48 hello.i
-rw-rw-r--+ 1 Administrator None 866 八月 3 17:18 hello.o
-rw-rw-r--+ 1 Administrator None 496 八月 3 17:05 hello.s
-rwxrwxr-x+ 1 Administrator None 155707 八月 3 17:26 hello11.exe
$ ./hello1.exe
hello world!
7、选项 -O(大写的字母O),使用编译优化级别,1~3,级别越大优化效果越好,但编译的时候会长。
$ gcc -O3 hello.c -o hello2
8、选项 -M,查看生成文件关联信息,包含目标文件所依赖的所有源代码,该命令会在预处理阶段中执行。
$ gcc -M hello.c
hello.o: hello.c /usr/include/stdio.h /usr/include/_ansi.h \
/usr/include/newlib.h /usr/include/_newlib_version.h \
/usr/include/sys/config.h /usr/include/machine/ieeefp.h \
/usr/include/sys/features.h /usr/include/cygwin/config.h \
/usr/include/sys/cdefs.h /usr/include/machine/_default_types.h \
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/stddef.h \
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/stdarg.h \
/usr/include/sys/reent.h /usr/include/_ansi.h /usr/include/sys/_types.h \
/usr/include/machine/_types.h /usr/include/sys/lock.h \
/usr/include/sys/types.h /usr/include/sys/_stdint.h \
/usr/include/machine/endian.h /usr/include/machine/_endian.h \
/usr/include/bits/endian.h /usr/include/sys/select.h \
/usr/include/sys/_sigset.h /usr/include/sys/_timeval.h \
/usr/include/sys/timespec.h /usr/include/sys/_timespec.h \
/usr/include/sys/_pthreadtypes.h /usr/include/machine/types.h \
/usr/include/endian.h /usr/include/bits/byteswap.h \
/usr/include/bits/wordsize.h /usr/include/sys/sysmacros.h \
/usr/include/sys/stdio.h
9、选项 -MM,与-M相比,会忽略#include文件的依赖关系
$ gcc -MM hello.c
hello.o: hello.c
10、多个文件一起编译,hello.c、multi.c分别编译后链接成multi.out或multi.exe的可执行文件。
$ gcc hello.c multi.c -o multi
11、多个.o二进制目标文件编译后链接成一个可执行文件
$ gcc multi.o hello.o -o multi1
12、选项 -include file :包含某个代码。相当于在文件中加入#include
$ gcc hello.c -include multi.c -o include
生成include.out可执行文件
13、选项 -Idir:当你使用#include”file”的时候,会先到你定制的目录里面查找。
14、选项 -L(library):定制编译的时候使用的库,/home/hello/lib作为第一个寻找库文件的目录。
$ gcc -o hello hello.c -L/home/hello/lib
15、选项 -l:定制编译的时候使用的库,寻找动态链接库文件libtest.so,如果加上-static,表示寻找libtest.a静态链接库。
$ gcc -o hello hello.c -ltest
16、选项 -w,表示不生成任何警告的信息。
$ gcc -w multi.c hello.c -o multi
17、选项 -Wall:生成所有警告信息。
$ gcc -Wall multi.c hello.c -o multi
18、选项 -g:在编译的时候加入debug调试信息,用于gdb调试,文件会比一般大一点。
$ gcc -g hello.c -o hello5
19、选项 -share:此选项尽量的使用动态库,所以生成文件比较小,但是必须是系统有动态库。
20、选项 -shared:生成共享目标文件,通常用在建立共享库。