参考资料:4.gcc和arm-linux-gcc_冷暖自知_源的博客-CSDN博客_arm-linux-gcc
浅析gcc、arm-linux-gcc和arm-elf-gcc的关系_求佛_ce123的博客-CSDN博客_arm-elf-gcc
目录
本质上都是编译器,而gcc是linux系统用来将代码编译成可执行程序的手段。编译出来的是适用于linux系统的可执行二进制文件。所以用gcc编译出来的可执行程序只有在linux系统下面可以运行。
arm-linux-gcc告诉编译器,我编写的环境是linux,但是我希望生成的可执行程序是在arm上面跑的。这就是交叉编译。编写环境和执行环境分离的一种手段。
GCC 内部结构主要由 Binutils、gcc-core、Glibc 等软件包组成。
1、Binutils:它是一组开发工具,包括连接器,汇编器和其他用于目标文件和档案的工具。关于 Binutils 的介绍可以参考 Binutils 简单介绍。这个软件包依赖于不同的目标机的平台。因为不同目标机的指令集是不一样的,比如 arm 跟 x86 就不一样。
2、gcc-core:GCC 的核心部分,这部分是只包含 c 的编译器及公共部分,而对其他语言(C++、Ada 等)的支持包需要另外安装,这也是 GCC 为何如此强大的重要原因 。gcc-core依赖于 Binutils。
3、Glibc:包含了主要的 c 库,这个库提供了基本的例程,用于分配内存,搜索目录,读写文件,字符串处理等等。kernel 和 bootloader不需要这个库的支持。
举例描述下上面 3 个包是如何进行运作的。有一个 c 源文件 test.c 源码如下:
#include<stdio.h>
int main(int argc, char *argv[])
{
printf("Hello Linux!!\n");
return 0;
}
编译命令为: gcc -o test test.c 编译生成 test 可执行文件。gcc 编译流程分为四个步骤:预处理、编译、汇编、链接。个人认为预处理和编译主要由 gcc-core 来完成,汇编和链接主要由 Binutils 来 完成。那么何时用到 glibc 呢?看到源码中的 printf 函数没有,这个函数在 GCC 中是以库函数的形式存在,这个库函数在 glibc 库中,在 stdio.h 头文件中被声明。
总的来说,如果真正了解了上面 3 个软件包的作用,自然就明白 GCC 是如何工作的。
如果要使用交叉工具链为 ARM 机器编译简单的 Hello World 程序,可以运行如下命令编译并测试这个代码: arm-linux-gcc -o hello hello.c。
arm-linux-gcc 是基于 ARM 目标机的交叉编译软件,x86 跟 ARM 所使用的指令集是不一样的,所以所需要的 binutils 肯定不一样;上面提到过 gcc-core 是依赖于 binutils 的,自然 ARM 跟 x86 所使用的 gcc-core 包也不一样;glibc 一个 c 库,最终是以库的形式存在于编译器中,自然 ARM 所使用的 glibc 库跟 x86 同样也不一样,其它的依此类推。
示例代码
#include<stdio.h>
int main(void)
{
printf("hello\n");
return 0;
}
预编译过程
这个过程处理宏定义和include,去除注释,不会对语法进行检查。
可以看到预编译后,代码从6行扩展到了910行。
1 2 3 4 5 |
|
编译过程
这个阶段,检查语法,生成汇编代码。
1 2 3 |
|
汇编过程
这个阶段,生成目标代码。
此过程生成ELF格式的目标代码。
1 2 3 |
|
链接过程
链接过程。生成可执行代码。链接分为两种,一种是静态链接,另外一种是动态链接。使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。使用动态链接的好处是,生成的程序比较小,占用较少的内存。
1 |
|
程序运行:
1 2 |
|
gcc hello.c直接编译,生成一个a.out的文件
gcc -o hello hello.c 使用-O选项指定文件输出,规定输出的文件名是hello
arm-linux-gcc 是交叉编译器,基本用法与 gcc 相同,目的是将编译的程序放在目标机(ARM)上运行。
以上面的hello.c文件为例说明arm-linux-gcc的用法
(1)$ arm-linux-gcc -o hello hello.c
生成可执行文件 hello,它包含了上述 4 个步骤(预处理、编译、汇编和链接)
(2)arm-linux-gcc -v -o hello hello.c
使用“arm-linux-gcc -v -o hello hello.c”命令可以查看编译的细节