有过单片机或者 ARM 嵌入式开发经验的小伙伴,都知道在写完一个程序之后,要对程序进行编译,那么在单片机上有 keil 、IAR 这样的集成环境供我们选择,在 win 上有 studio 这种环境,但是进入了 linux 的世界,这些常见的就都不见踪影了,一切都要从新开始。在 linux 上也就是 ubuntu 上编译程序使用的是 gcc 。
1.1 gcc 简介
GCC(GNU Compiler Collection)是一个由GNU项目开发的编译器系统,用于编译多种编程语言的源代码。最初,GCC 仅作为 C 语言的编译器(GNU C Compiler),但随着时间的推移,它发展成为支持多种语言的编译器集合,因此现在的全称是 GNU Compiler Collection。
GCC(GNU Compiler Collection)是一个强大的编译器系统,广泛用于编译 C、C++、Objective-C、Fortran、Ada 和其他多种编程语言的代码。gcc 可以支持多种计算机体系结构,比如 X86、 ARM 、MIPI 等,ubuntu 默认自带 gcc,输入命令 gcc -v 来查看 gcc 的版本,如下图所示:
由上图我们可以得知 gcc 的版本为9.4.0
1.2 gcc的基本用法
基本命令格式:gcc [选项] [文件名]
使用命令 vim helloworld.c 创建 helloworld.c 文件,如下图所示:
在该文件中添加如下内容:
保存并退出。
我们使用 cat 指令来查看该文件中的内容,如下图所示。
保存退出之后,使用命令 gcc helloworld.c -o helloworld , 如下图所示:
输入 ./helloworld 运行helloworld文件,./的意思是在当前目录找到 helloworld 文件并执行。
如果不使用 -o 参数指定生成文件的名称,直接输入 gcc helloworld.c 编译完会得到一个 a.out 文件,执行这个 a.out 的结构和执行 hello 是一样的。
file 命令:
功能:查看文件类型
格式: file [文件名]
下图给出了查看 helloworld 文件类型的过程。
使用虚拟机 ubuntu 自带的 gcc 编译器编译出来的可执行文件是 X86 的,不能在 arm 开发板上运行。可以使用 file 命令来查看文件类型。
1.3 编译过程
从 helloworld .c 编译得到 helloworld 或者 a.out 要经历四个步骤:预处理,编译,汇编, 链接。
helloworld .i 预处理得到的 C 语言代码
helloworld .s 汇编语言文件
helloworld .o 目标文件
第一阶段:预处理阶段,编译器会对头文件或者宏定义进行展开,或者条件编译的选择可以使用 -E 参数得到预处理文件 。
-E参数:只对文件进行预处理,不编译和链接。
使用命令 gcc -E helloworld.c -o helloworld.i 得到预处理后的文件,如下图所示:
helloworld.i 文件内容如下图所示:
第二阶段:编译,把文件编译成汇编代码
-S 参数:将 helloworld.i 文件编译成 helloworld.s 文件
第三阶段:汇编,把汇编文件编译机器码
-c 参数:可以把 helloworld.s 文件编译成 helloworld.o 文件
第四阶段:链接
直接把目标文件编译成可执行文件
链接分为静态链接和动态链接,gcc 默认的是动态链接。
特点:生成的程序小,但是需要依赖库;
静态链接:使用 -static 参数就是静态链接,因为程序里面包含了需要的库,所以体积比较大。
关于静态链接和动态链接详细请参考:
静态链接和动态链接-CSDN博客
1.4 GCC的主要功能
-
编译:GCC 将源代码编译为机器码(通常是目标文件),这一步骤将高层次的编程语言转换为计算机可以执行的低层次指令。
-
预处理:在实际编译之前,GCC 进行预处理,处理宏、头文件包含等。预处理是通过
gcc -E
命令来完成的。 -
汇编:GCC 还可以将编译后的中间代码转换为汇编代码,这是机器代码的更低级表示。可以通过
gcc -S
命令生成汇编代码。 -
链接:在编译完成后,GCC 将目标文件与库文件链接在一起,生成最终的可执行文件。链接器的功能通常由
ld
工具完成,但在使用 GCC 时,链接过程是自动完成的。 -
优化:GCC 提供了多种优化选项,用于提高生成的代码的性能。优化选项可以针对特定的体系结构或应用需求进行调整,如
-O2
(标准优化)或-O3
(更高级的优化)。 -
调试支持:GCC 可以生成带有调试信息的可执行文件,这样开发者可以使用调试器(如
gdb
)来调试程序。这通常通过-g
选项实现。