ARM_Linux中GCC编译器的使用

目录

前言:

GCC编译过程:

预处理:

编译阶段:

汇编:

链接阶段

GCC的常见使用


前言:

什么是GCC:

gcc的全称是GNU Compiler Collection,它是一个能够编译多种语言的编译器。最开始gcc是作为C语言的编译器(GNU C Compiler),现在除了c语言,还支持C++、java、Pascal等语言。gcc支持多种硬件平台。

特点:

  • gcc是一个可移植的编译器,支持多种硬件平台。例如ARM、X86等等。
  • gcc不仅是个本地编译器,它还能跨平台交叉编译。所谓的本地编译器,是指编译出来的程序只能够在本地环境进行运行。而gcc编译出来的程序能够在其他平台进行运行。例如嵌入式程序可在x86上编译,然后在arm上运行。
  • gcc有多种语言前端,用于解析不同的语言。
  • gcc是按模块化设计的,可以加入新语言和新CPU架构的支持。
  • gcc是自由软件。任何人都可以使用或更改这个软件。

        源文件需要经过编译才能够生成可执行文件,在Windows下进行开发的时候,只需要几个按键就可以编译,集成的开发环境(V Studio,keil,clion等)已经将各种编译工具封装好了,linux中虽然有一些集成好的编译器,但是对于嵌入式软件开发的时候,通常没有屏幕,只能通过指令进行程序的编写和调试。但是要编译出来的程序可以在ARM上运行,就必须使用交叉编译器xxx-gcc等。

GCC编译过程:

一个c/c++文件要经过四个过程才能变成可执行文件。

  • 预编译(Pre-Processing)
  • 编译(Compiling)
  • 汇编(Assembling)
  • 链接(Linking)

预处理:

预处理过程中,是对源代码文件中的包含(include)、预编译语句(以#开头的命令等)进行展开生成.i文件。

使用GCC的参数 “-E”,可以让编译器生成 .i 文件,参数 “-o”,可以指定输出文件的名字。

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

预处理就是将要包含“#include”的文件插入到原文件中,将宏定义展开,根据条件编译命令选择要使用的代码,最后将这些东西输入到“.i”文件中等待进一步处理

编译阶段:

gcc调用不同语言的编译器,例如c语言调用编译器ccl。gcc实际上是个工具链,在编译程序的过程中调用不同的工具。而在编译阶段就是通过调用的工具将预处理后的.i文件编译成汇编语言,生成.s文件,就是把代码从C语言转为汇编语言。在这个过程,GCC会检查各个源文件的语法。

GCC可以使用-S选项,让编译程序生成汇编语言的代码文件(.s后缀)。

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

了解过汇编语言的应该知道,对于不同的芯片会由不同的汇编指令集,这个是没法通用的。所以这是为什么要使用交叉编译器的一个主要原因。

汇编:

汇编阶段,gcc调用汇编器进行汇编。将汇编语言的.s文件经过汇编生成.o文件,每一个源文件都对应一个目标文件。把汇编语言转换成机器码。

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

双击.o文件是打不开的,使用vim打开也是一堆乱码,这是因为Linux下生成的.o目标文件、.so动态库文件以及可执行文件都是elf格式的。可以使用“readelf”工具来查看内容。

从 readelf 的工具输出的信息,可以了解到目标文件包含ELF头、程序头、节等内容, 对于*.o目标文件或*.so库文件,编译器在链接阶段利用这些信息把多个文件组织起来。

链接阶段

最后将每个源文件对应的目标文件.o链接起来,就生成一个成执行文件了。

例如一个工程里包含了A和B两个代码文件,在链接阶段, 链接过程需要把A和B之间的函数调用关系理顺,也就是说要告诉A在哪里能够调用到fun函数, 建立映射关系,所以称之为链接。若链接过程中找不到fun函数的具体定义,则会链接报错。

虽然文章的test1例子中只有一个.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

从图中可以看到,使用动态链接生成的hello程序才16.6KB, 而使用静态链接生成的hello_static程序则高达871.9KB。

在Ubuntu下,可以使用 ldd 工具查看动态文件的库依赖,尝试执行如下命令:

但是静态链接生成的可执行文件没有依赖外部库文件。

GCC的常见使用

//gcc使用示例
gcc hello.c // 输出一个名为 a.out的可执行程序,然后可以执行./a.out
gcc -o hello hello.c // 输出名为 hello的可执行程序,然后可以执行./hello
gcc -o hello hello.c -static // 静态链接
gcc -c -o hello.o hello.c // 先编译(不链接)
gcc -o hello hello.o // 再链接

执行“gcc -o test1 test1.c -v”的时候可以看到这写步骤

常用编译选项:

多文件编译

//一次性编译
gcc -o main  hello.c main.c //生成可执行文件main
//独立编译
gcc -Wall -c-o main.o main.c 
gcc -Wall -c -o hello.o hello.c
gcc -Wall -o main main.o hello.o

制作动态库:

静态库:

文章参考:

GCC基本使用 - 知乎 (zhihu.com)

Linux编译工具:gcc入门 - melonstreet - 博客园 (cnblogs.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/243319.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习记录--指数加权平均

指数加权移动平均(exponentially weighted moving averages) 如何对杂乱的数据进行拟合? 通过指数加权平均可以把数据图近似拟合成一条曲线 公式: 其中表示第t个平均数,表示第t-1个平均数,表示第t个数据,表示变化参数…

tkinter绘制组件(40)——滚动选值框

tkinter绘制组件(40)——滚动选值框 引言布局函数结构文本展示选择器布局完整函数代码 效果测试代码最终效果 github项目pip下载结语 引言 2023年基本没有怎么更新TinUI组件部分,而滚动选值框(picker),是在…

《WebKit 技术内幕》学习之七(4): 渲染基础

4 WebKit软件渲染技术 4.1 软件渲染过程 在很多情况下,也就是没有那些需要硬件加速内容的时候(包括但不限于CSS3 3D变形、CSS3 03D变换、WebGL和视频),WebKit可以使用软件渲染技术来完成页面的绘制工作(除非读者强行…

Vue基础入门 - Vue的快速创建、Vue的开发者工具安装及Vue的常用指令(v-model,v-bind,computed计算属性,watch侦听器)

Vue 文章目录 Vue1 什么是Vue2 创建Vue实例2.1 快速创建2.2 插值表达式 {{}}2.3 响应式特性2.3.1 访问与修改 3 Vue开发者工具安装4 Vue中的常用指令4.1 内容渲染指令4.2 条件渲染指令4.3 事件绑定指令4.4 属性绑定指令4.5 案例-上下页图片翻页4.6 列表渲染指令4.7 案例-能删除…

flink部署模式介绍

在一些应用场景中,对于集群资源分配和占用的方式,可能会有特定的需求。Flink 为各种场景提供了不同的部署模式,主要有以下三种,它们的区别主要在于: 集群的生命周期以及资源的分配方式;应用的 main 方法到…

谷歌浏览器通过network模拟HTTP中的GET/POST请求获取response

1、F12打开network选中需要模拟的方法Copy->Copy as fetch 2、通过AI帮你进行转换一下调用格式 原代码 fetch("https://mp.amap.com/api/forward/aggregate?mtop.alsc.kbt.intergration.toolkit.call.queryCallBlockInfo", {"headers": {"acce…

03--数据库连接池

1、数据库连接池 1.1 JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet、beans)中建立数据库连接进行sql操作断开数据库连接 这种模式开发,存在的问题:…

PyTorch 中的距离函数深度解析:掌握向量间的距离和相似度计算

目录 Pytorch中Distance functions详解 pairwise_distance 用途 用法 参数 数学理论公式 示例代码 cosine_similarity 用途 用法 参数 数学理论 示例代码 输出结果 pdist 用途 用法 参数 数学理论 示例代码 总结 Pytorch中Distance functions详解 pair…

Git学习笔记(第1章):Git概述

目录 1.1 版本控制 1.1.1 何为版本控制 1.1.2 为什么需要版本控制 1.1.3 版本控制工具 1.2 发展历史 1.3 工作机制 1.4 代码托管中心(远程库) Git是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。…

【UEFI基础】EDK网络框架(UDP4)

UDP4 UDP4协议说明 UDP的全称是User Datagram Protocol,它不提供复杂的控制机制,仅利用IP提供面向无连接的通信服务。它将上层应用程序发来的数据在收到的那一刻,立即按照原样发送到网络。 UDP报文格式: 各个参数说明如下&…

AD导出BOM表 导出PDF

1.Simple BOM: 这种模式下,最好在pcb界面,这样的导出的文件名字是工程名字,要是在原理图界面导出,会以原理图的名字命名表格。 直接在菜单栏 报告->Simple BOM 即可导出物料清单,默认导出 comment pattern qu…

【Java】学习一门开发语言,从TA的Hello World开始

欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《Java》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握…

【Redis】非关系型数据库之Redis的主从复制、哨兵和集群高可用

目录 一、主从复制、哨兵、集群的区别 二、主从复制 2.1主从复制的作用 2.2主从复制的原理 2.3主从复制的实操 步骤一:环境准备 步骤二:安装Redis以及配置文件修改 Redis的主从配置文件都一样 步骤四:验证主从复制 三、哨兵 3.1哨兵…

NODE介绍和环境安装

浏览器是JS的前端运行环境 Node.js是JS的后端运行环境 Node.js中无法调用DOM和BOM等浏览器内置API 基于Express框架,快速构建web应用 基于Electron框架,构建跨平台桌面应用 基于restify框架快速构建API接口项目 读写数据库 下载Node.js环境 网址&…

【分布式技术】注册中心zookeeper

目录 一、ZooKeeper是什么 二、ZooKeeper的工作机制 三、ZooKeeper特点 四、ZooKeeper数据结构 五、ZooKeeper应用场景 ●统一命名服务 ●统一配置管理 ●统一集群管理 ●服务器动态上下线 ●软负载均衡 六、ZooKeeper的选举机制 七、实操部署ZooKeeper集群 步骤一…

线性代数:矩阵运算(加减、数乘、乘法、幂、除、转置)

目录 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式,证明:|AB| |A| |B| 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式,证明:|AB| |A| |B|

续签KES证书

MiniO KES(密钥加密服务)是 MinIO 开发的一项服务,旨在弥合在 Kubernetes 中运行的应用程序与集中式密钥管理服务 (KMS) 之间的差距。中央 KMS 服务器包含所有状态信息,而 KES 在需要执行与获取新密钥或更新…

Unity 工厂方法模式(实例详解)

文章目录 在Unity中,工厂方法模式是一种创建对象的常用设计模式,它提供了一个接口用于创建对象,而具体的产品类是由子类决定的。这样可以将对象的创建过程与使用过程解耦,使得代码更加灵活和可扩展。 工厂模式的主要优点如下&…

Unity中实现捏脸系统

前言 目前市面上常见的捏脸一般是基于BlendShapes和控制骨骼点坐标两种方案实现的。后者能够控制的精细程度更高,同时使用BlendShapes来控制表情。 控制骨骼点坐标 比如找到控制鼻子的骨骼节点修改localScale缩放,调节鼻子大小。 BlendShapes控制表…

gin中间件篇

1. 全局中间件 所有请求都经过此中间件 package mainimport ("fmt""time""github.com/gin-gonic/gin" )// 定义中间 func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t : time.Now()fmt.Println("中间件开始执行了&quo…