gcc编译器

1. GCC工具

GCC编译器:
GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器。 GCC最初代表“GNU C Compiler”,当时只支持C语言。 后来又扩展能够支持更多编程语言,包括 C++、Fortran 和 Java 等。 因此,GCC也被重新定义为“GNU Compiler Collection”,成为历史上最优秀的编译器, 其执行效率与一般的编译器相比平均效率要高 20%~30%。
GCC的官网地址为:https://gcc.gnu.org/,在Ubuntu系统下系统默认已经安装好GCC编译器,可以通过如下命令查看Ubuntu系统中GCC编译器的版本及安装路径:
在这里插入图片描述

GCC编译工具链:

GCC编译工具链(toolchain),是指以GCC编译器为核心的一整套工具。它主要包含以下三部分内容:

gcc-core:即GCC编译器,用于完成预处理和编译过程,把C代码转换成汇编代码。
Binutils :除GCC编译器外的一系列小工具包括了链接器ld,汇编器as、目标文件格式查看器readelf等。
glibc:包含了主要的 C语言标准函数库,C语言中常常使用的打印函数printf、malloc函数就在glibc 库中。

在很多场合下会直接用GCC编译器来指代整套GCC编译工具链。

Binutils工具集:

Binutils(bin utility),是GNU二进制工具集,通常跟GCC编译器一起打包安装到系统,它的官方说明网站地址为: https://www.gnu.org/software/binutils/ 。
在进行程序开发的时候通常不会直接调用这些工具,而是在使用GCC编译指令的时候由GCC编译器间接调用。下面是其中一些常用的工具:

as:汇编器,把汇编语言代码转换为机器码(目标文件)。
ld:链接器,把编译生成的多个目标文件组织成最终的可执行程序文件。
readelf:可用于查看目标文件或可执行程序文件的信息。
nm : 可用于查看目标文件中出现的符号。
objcopy: 可用于目标文件格式转换,如.bin 转换成 .elf 、.elf 转换成 .bin等。
objdump:可用于查看目标文件的信息,最主要的作用是反汇编。
size:可用于查看目标文件不同部分的尺寸和总尺寸,例如代码段大小、数据段大小、使用的静态内存、总大小等。

系统默认的Binutils工具集位于/usr/bin目录下,可使用如下命令查看系统中存在的Binutils工具集:

ls /usr/bin/ | grep linux-gnu-

glibc库:

glibc库是GNU组织为GNU系统以及Linux系统编写的C语言标准库,因为绝大部分C程序都依赖该函数库,该文件甚至会直接影响到系统的正常运行,例如常用的文件操作函数read、write、open,打印函数printf、动态内存申请函数malloc等。
在Ubuntu系统下,libc.so.6是glibc的库文件,可直接执行该库文件查看版本,在主机上执行如下命令:
glibc库文件路径,可直接执行:

/lib/x86_64-linux-gnu/libc.so.6

GCC编译

1.编写程序源码

#include <stdio.h>
int main()
{
printf("hello, world! This is a C program.\n");
for(int i=0;i<10;i++ ){
printf("output i=%d\n",i);
}
return 0;
}
# 在Ubuntu的hello_c目录下执行如下命令
gcc hello.c –o hello #使用gcc把hello.c编译成hello程序
ls #查看目录下的文件
./hello #执行生成的hello程序

GCC 编译工具链在编译一个C源文件时需要经过以下 4 步:

预处理:为把头文件的代码、宏之类的内容转换成生成的.i文件,还是C代码。
编译:把预处理后的.i文件通过编译成.s文件,汇编语言。
汇编:将汇编语言文件生成目标文件.o文件,机器码。
链接:将每个源文件对应的.o文件链接起来,就生成一个可执行程序文件。

(1)预处理阶段

预处理过程中,对源代码文件中的文件包含 (include)、 预编译语句 (如宏定义define等)进行展开,生成 .i 文件。 可理解为把头文件的代码、宏之类的内容转换成更纯粹的C代码,不过生成的文件以.i为后缀。
使用GCC的参数 “-E”,可以让编译器生成 .i 文件,参数 “-o”,可以指定输出文件的名字。
具体命令如下:

预处理,可理解为把头文件的代码汇总成C代码,把*.c转换得到*.i文件
gcc –E hello.c –o hello.i

相当于它把原C代码中包含的头文件中引用的内容汇总到一处, 如果原C代码有宏定义,它把宏定义展开成具体的内容。

(2)编译阶段

把预处理后的.i文件通过编译成为汇编语言,生成.s文件,即把代码从C语言转换成汇编语言,这是GCC编译器完成的工作。在这个过程,GCC会检查各个源文件的语法,即使我们调用了一个没有定义的函数,也不会报错。
GCC可以使用-S选项,让编译程序生成汇编语言的代码文件(.s后缀)。
具体命令如下:

 #编译,可理解为把C代码转换为汇编代码,把*.i转换得到*.s文件
gcc –S hello.i –o hello.s
#也可以直接以C文件作为输入进行编译,与上面的命令是等价的
gcc –S hello.c –o hello.s

(3)汇编阶段

将汇编语言文件经过汇编,生成目标文件.o文件,每一个源文件都对应一个目标文件。即把汇编语言的代码转换成机器码,这是as汇编器完成的工作。
GCC的参数“c”表示只编译(compile)源文件但不链接,会将源程序编译成目标文件(.o后缀)。计算机只认识0或者1,不懂得C语言,也不懂得汇编语言,经过编译汇编之后,生成的目标文件包含着机器代码,这部分代码就可以直接被计算机执行。一般情况下,可以直接使用参数“c”,跳过上述的两个过程,具体命令 如下:

# 汇编,可理解为把汇编代码转换为机器码,把*.s转换得到*.o,即目标文件
gcc –c hello.s –o hello.o
# 也可以直接以C文件作为输入进行汇编,与上面的命令是等价的
gcc –c hello.c –o hello.o

(4)链接阶段

最后将每个源文件对应的目标.o文件链接起来,就生成一个可执行程序文件,这是链接器ld完成的工作。
例如一个工程里包含了A和B两个代码文件,在链接阶段, 链接过程需要把A和B之间的函数调用关系理顺,也就是说要告诉A在哪里能够调用到fun函数, 建立映射关系,所以称之为链接。若链接过程中找不到fun函数的具体定义,则会链接报错。
虽然本示例只有一个hello.c文件,但它调用了C标准代码库的printf函数, 所以链接器会把它和printf函数链接起来,生成最终的可执行文件。
链接分为两种:

动态链接:GCC编译时的默认选项。动态是指在应用程序运行时才去加载外部的代码库,不同的程序可以共用代码库。 所以动态链接生成的程序比较小,占用较少的内存。
静态链接:链接时使用选项 “–static”,它在编译阶段就会把所有用到的库打包到自己的可执行程序中。 所以静态链接的优点是具有较好的兼容性,不依赖外部环境,但是生成的程序比较大。

执行如下命令体验静态链接与动态链接的区别:

# 在hello.o所在的目录执行如下命令
# 动态链接,生成名为hello的可执行文件
gcc hello.o –o hello
# 也可以直接使用C文件一步生成,与上面的命令等价
gcc hello.c -o hello
# 静态链接,使用--static参数,生成名为hello_static的可执行文件
gcc hello.o –o hello_static --static
# 也可以直接使用C文件一步生成,与上面的命令等价
gcc hello.c -o hello_static --static

在Ubuntu下,可以使用 ldd 工具查看动态文件的库依赖

3. 交叉编译

如果我们希望编译器运行在x86架构平台上,然后编译生成ARM架构的可执行程序,这种编译器和目标程序运行在不同架构的编译过程,被称为 交叉编译

安装ARM-GCC
# 在主机上执行如下命令
sudo apt install gcc-arm-linux-gnueabihf
# 安装完成后使用如下命令查看版本
arm-linux-gnueabihf-gcc –v

交叉编译程序

交叉编译器与本地编译器使用起来并没有多大区别。

# 在hello.c程序所在的目录执行如下命令
arm-linux-gnueabihf-gcc hello.c –o hello_arm

同样的C代码文件,使用交叉编译器编译后,生成的hello已经变成了ARM平台的可执行文件,可以通过readelf工具来查看具体的程序信息

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RISC-V GCC编译器手册是一本详细介绍如何使用RISC-V架构下GCC编译器的参考手册。GCC是一种自由软件,被广泛用于编译各种编程语言,包括C、C++和Fortran等。RISC-V是一种基于精简指令集计算机(RISC)原理的开源处理器架构。 手册中首先介绍了RISC-V工具链的安装和配置,包括如何获取GCC编译器和相关的工具。它详细说明了如何在不同的操作系统上进行编译器和工具链的安装过程,并提供了一些常见问题的解答。 接下来,手册详细介绍了GCC编译器的各种选项和参数的用法。这些选项和参数可以用于控制编译器的行为,如优化级别、调试选项、错误处理、输出文件格式等。手册还提供了一些示例和说明,以帮助用户理解和使用这些选项。 此外,手册还涵盖了GCC编译器针对RISC-V架构的特定优化策略。这些优化策略可以提高代码的性能和效率,包括指令调度、寄存器分配、循环优化等。手册中还解释了如何使用这些优化选项,并给出了一些示例来说明其作用。 最后,手册还包括对GCC编译器的一些扩展功能的介绍,如内联汇编、向量指令集扩展、浮点运算支持等。这些扩展功能使得GCC编译器能够更好地支持RISC-V架构下特定的编程需求。 总之,RISC-V GCC编译器手册是一本详细、全面的参考手册,为用户提供了使用GCC编译器进行RISC-V架构开发的必备指南。无论是初学者还是有经验的开发者,都可以通过这本手册深入了解和掌握GCC编译器的用法,从而更加高效地进行RISC-V架构下的软件开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值