Keil中的gcc
文章目录
- 一、IDE背后的命令
- 1.1 IDE是什么
- 1.2 IDE的背后是命令
- 1.3 有两套主要的编译器
- 二、准备工作
- 2.1 arm-linux-gcc和gcc是类似的
- 2.2 Code::Blocks
- 2.2.1 设置windows环境变量
- 2.2.2 命令行示例
- 三、gcc编译过程详解
- 3.1 程序编译4步骤
- 3.2 gcc的使用方法
- 3.2.1 gcc使用示例
- 3.2.2 gcc常用选项
- 1.手工控制编译过程
- 2.使用后缀名决定编译过程
- 3.2.3 指定头文件目录
- 3.2.4 指定库文件
一、IDE背后的命令
1.1 IDE是什么
IDE指集成开发环境(Integrated Development Environment)。
我们开发STM32F103等单片机程序时使用是keil就是一种IDE。
使用IDE,很容易操作,点点鼠标就可完成:
- 添加文件
- 指定文件路径(头文件路径、库文件路径)
- 指定链接库
- 编译、链接
- 下载、调试
1.2 IDE的背后是命令
使用CMD来查看编译结果(这里使用第一个点灯程序为例):
如图勾上该选项:
用Note++查看生成的BAT文件:
用Note++分别查看main__i、start_ia、led_c_lnp,加上上图的编译语句:
打开CMD,进入到led.c的文件目录
进入到该文件目录下后复制上面红框内整合到一起的命令,可以看到其中的输出结果与Keil编译结果一样:
-
注意
- 使用GitBash执行命令的话
由于GitBash采用类似Linux的文件路径表示方法(比如 /d/abc,而非 d:\abc),命令行中windows格式的路径名要加上双引号,比如".\objects\main.o"
- 使用dos命令行执行命令的话
不需要加双引号
- 使用GitBash执行命令的话
-
在某个Keil工程所在目录下,打开Git Bash:
E:\ARM\doc_and_source_for_mcu_mpu\STM32MF103\daima\led_c
-
编译main.c
执行命令:"E:\keil5\ARM\ARMCC\Bin\ArmCC" --c99 --gnu -c --cpu Cortex-M3 -D__EVAL -g -O0 --apcs=interwork --split_sections -I.\RTE\_led_c -I"C:\Users\thisway_diy\AppData\Local\Arm\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include" -I"C:\Keil_v5\ARM\CMSIS\Include" -D__UVISION_VERSION="527" -DSTM32F10X_HD -o ".\objects\main.o" --omf_browse ".\objects\main.crf" --depend ".\objects\main.d" "main.c"
-
编译start.S
执行命令:"E:\keil5\ARM\ARMCC\Bin\ArmAsm" --cpu Cortex-M3 --pd "__EVAL SETA 1" -g --apcs=interwork -I.\RTE\_led_c -I"C:\Users\thisway_diy\AppData\Local\Arm\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include" -I"C:\Keil_v5\ARM\CMSIS\Include" --pd "__UVISION_VERSION SETA 527" --pd "STM32F10X_HD SETA 1" --list ".\listings\start.lst" --xref -o ".\objects\start.o" --depend ".\objects\start.d" "start.s"
-
链接
执行命令:"E:\keil5\ARM\ARMCC\Bin\ArmLink" --cpu Cortex-M3 ".\objects\main.o" ".\objects\start.o" --ro-base 0x08000000 --entry 0x08000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors --strict --summary_stderr --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers --list ".\Listings\led_c.map" -o ".\Objects\led_c.axf"
1.3 有两套主要的编译器
-
armcc
- ARM公司的编译器
- keil使用的就是armcc
-
gcc
- GNU工具链
- Linux等开源软件经常使用gcc
后面以GNU工具链为例讲解,所涉及的知识可以平移到armcc上。
二、准备工作
2.1 arm-linux-gcc和gcc是类似的
- arm-linux-gcc
- 给ARM芯片编译程序
- gcc
- 在x86编译程序
- 用法基本一样
- 为方便演示,我们使用gcc
- 为了方便在windows下演示,我们使用
Code::Blocks
- 它的安装程序自带gcc
2.2 Code::Blocks
它是一款基于GCC的windows IDE,可以用来开发C/C++/Fortran。
官网地址:http://www.codeblocks.org/
可以使用百问网韦东山老师提供的Git仓库下载:git clone https://e.coding.net/weidongshan/noos/cortexA7_windows_tools.git
下载GIT后,在apps目录下。
2.2.1 设置windows环境变量
在Path环境变量中添加:C:\Program Files\CodeBlocks\MinGW\bin
2.2.2 命令行示例
事先写好一个hello.c放在E盘,启动Git Bash,编译程序hello.c:
#include <stdio.h>int main(void)
{printf("hello, world!\n");return 0;
}
编译、运行命令如下:
gcc -o hello hello.c
./hello.exe
三、gcc编译过程详解
3.1 程序编译4步骤
我们经常使用“编译”泛指上面的4个步骤之一,甚至有时候会囊括这四个步骤。
3.2 gcc的使用方法
gcc [选项] 文件名
3.2.1 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 // 再链接
3.2.2 gcc常用选项
1.手工控制编译过程
选项 | 功能 |
---|---|
-v | 查看gcc编译器的版本,显示gcc执行时的详细过程 |
-o | 指定输出文件名为file,这个名称不能跟源文件名同名 |
-E | 只预处理,不会编译、汇编、链接t |
-S | 只编译,不会汇编、链接 |
-c | 编译和汇编,不会链接 |
一个c/c++文件要经过预处理、编译、汇编和链接才能变成可执行文件。
(1)预处理
C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理。
(2)编译
编译就是把C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码。
(3)汇编
汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现为ELF目标文件(OBJ文件)。“反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。
(4)链接
链接就是将上步生成的OBJ文件和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件。
hello.c(预处理)->hello.i(编译)->hello.s(汇编)->hello.o(链接)->hello
详细的每一步命令如下:
gcc -E -o hello.i hello.c
gcc -S -o hello.s hello.i
gcc -c -o hello.o hello.s
gcc -o hello hello.o
上面一连串命令比较麻烦,gcc会对.c文件默认进行预处理操作,使用-c再来指明了编译、汇编,从而得到.o文件,
再将.o文件进行链接,得到可执行应用程序。简化如下:
gcc -c -o hello.o hello.c
gcc -o hello hello.o
我们事先写了一个hello.c,通过调用gcc指令查看编译细节:
#include <stdio.h>#define MAX 20
#define MIN 10 #define _DEBUG
#define SetBit(x) (1<<x) int main(int argc, char* argv[])
{printf("Hello World \n");printf("MAX = %d,MIN = %d,MAX + MIN = %d\n",MAX,MIN,MAX + MIN); #ifdef _DEBUGprintf("SetBit(5) = %d,SetBit(6) = %d\n",SetBit(5),SetBit(6));printf("SetBit( SetBit(2) ) = %d\n",SetBit( SetBit(2) ));
#endif return 0;
}
直接编译运行如下:
但此时我们输入以下命令会发现有所不同:
gcc -o hello hello.c -v
会发现出现了很多信息,但其中主要的是以下几条:
执行预处理命令:
gcc -E -o hello.i hello.c//预处理
可见对应的宏会被包含进来,同时define中的代码也会直接使用:
观察去掉define后的输出结果:
若在mian.c中输入其他错误代码,观察是否有报错现象:
执行编译命令:
gcc -S -o hello.s hello.i//编译
可见编译时会报错:
去除掉报错字符,观察结果:
可见删除之后编译通过,不会有报错。
执行汇编命令:
gcc -c -o hello.o hello.s
执行链接指令:
gcc -o hello hello.o
2.使用后缀名决定编译过程
参考《嵌入式Linux应用开发完全手册》
:
- 总结
- 输入文件的后缀名和选项共同决定gcc到底执行那些操作
- 在编译过程中,最后的步骤都是链接
- 除非使用了-E、-S、-c选项
- 或者编译出错阻止了完整的编译过程
3.2.3 指定头文件目录
头文件在哪里?
-
系统目录
-
系统目录在哪?工具链里的某个include目录
-
怎么确定?
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)
-
可以不使用系统include目录吗?可以,编译时指定参数
-nostdinc
-
-
可以自己指定头文件目录
-I <头文件目录>
3.2.4 指定库文件
库文件在哪里?
-
系统目录
-
系统目录在哪?工具链里的某个lib目录
-
怎么确定?
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)
-
可以不使用系统lib目录吗?可以,编译时指定参数
-nostdlib
-
-
可以自己指定库文件目录
-L <库文件目录>
- 指定库文件
-l <abc> // 链接 libabc.so 或 lib.a
相关文章:

Keil中的gcc
文章目录 一、IDE背后的命令1.1 IDE是什么1.2 IDE的背后是命令1.3 有两套主要的编译器 二、准备工作2.1 arm-linux-gcc和gcc是类似的2.2 Code::Blocks2.2.1 设置windows环境变量2.2.2 命令行示例 三、gcc编译过程详解3.1 程序编译4步骤3.2 gcc的使用方法3.2.1 gcc使用示例3.2.2…...

bilibili 哔哩哔哩小游戏SDK接入
小游戏的文档 简介 bilibili小游戏bilibili小游戏具有便捷、轻量、免安装的特点。游戏包由云端托管,在哔哩哔哩APP内投放和运行,体验流畅,安全可靠。https://miniapp.bilibili.com/small-game-doc/guide/intro/ 没想过接入这个sdk比ios还难…...

springboot523基于Spring Boot的大学校园生活信息平台的设计与实现(论文+源码)_kaic
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本大学校园生活信息平台就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据…...

【YOLO算法改进】ALSS-YOLO:无人机热红外图像|野生动物小目标检测
目录 论文信息 论文创新点 1.自适应轻量通道分割和洗牌(ALSS)模块 2.轻量坐标注意力(LCA)模块 3.单通道聚焦模块 4.FineSIOU损失函数 摘要 架构设计 轻量高效网络架构 - ALSS模块 LCA模块 单通道聚焦模块 损失函数优…...

XML解析
一,XML概述 1.什么是XML XML即为可扩展的标记语言(eXtensible Markup Language) XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识 2.XML和HTML不同之处 XML主要用于说明文档的主题,而…...

PlasmidFinder:质粒复制子的鉴定和分型
质粒(Plasmid)是一种细菌染色体外的线性或环状DNA分子,也是一种重要的遗传元素,它们具有自主复制能力,可以在细菌之间传播,并携带多种重要的基因(如耐药基因与毒力基因等)功能。根据质粒传播的特性…...
PTA数据结构作业一
6-1 链表的插入算法 本题要求实现一个插入函数,实现在链表llist中的元素x之后插入一个元素y的操作。 函数接口定义: int InsertPost_link(LinkList llist, DataType x, DataType y); 其中 llist是操作的链表,x是待插入元素y的前驱节点元素…...

2024年总结【第五年了】
2024年总结 北国绕院扫雪,南方围炉烹茶,且饮一杯无? 执笔温暖不曾起舞日子里的点点滴滴,誊写一段回忆,还以光阴一段副本。 那么你要听一支新故事吗?第五年总结的片碎。 衣单天寒,走趟流星孤骑…...
java实现一个kmp算法
1、什么是KMP算法 Kmp 算法是由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,改进字符串匹配的算法; Kmp 算法的核心是利用匹配失败的信息,尽量减少模式串与主串的匹配次数,以达到 快速匹配的目的; Kmp 算法的时…...
强化学习方法分类详解
强化学习方法分类详解 引言 强化学习(Reinforcement Learning, RL)是一种通过智能体与环境互动来学习如何做出最佳决策的方法。根据不同的优化中心、策略特性、环境模型、奖励函数、动作空间类型以及行为策略和目标策略的一致性,RL可以分为…...
雅思真题短语(二十八)
真题短语收录在合辑。 541法律官员 work as a solicitor 542前卫 a radical and expensive scheme 543反对者们 objectors 544破坏 demolishing buildings 545蒸汽机车 steam locomotives 546冷凝 steam could be condensed 547烟雾 smoke and fumes 548通风井 ventilation sh…...

在Linux系统中使用字符图案和VNC运行Qt Widgets程序
大部分服务器并没有GUI,运行的是基础的Linux系统,甚至是容器。如果我们需要在这些系统中运行带有GUI功能的Qt程序,一般情况下就会报错,比如: $ ./collidingmice qt.qpa.xcb: could not connect to display qt.qpa.plu…...

Python基于EasyOCR进行路灯控制箱图像文本识别项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 随着城市化进程的加快,智能城市建设成为了现代社会发展的重要方向。路灯作为城市基础设…...
Github 2024-12-28 Rust开源项目日报 Top10
根据Github Trendings的统计,今日(2024-12-28统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目1Python项目1egui: 一个简单、快速且高度可移植的 Rust GUI 库 创建周期:1903 天开发语言:Rust协议类型:Apache Li…...
提升生产力工具
VSCODE插件 干货:用好这13款VSCode插件,工作效率提升10倍 - 程序员柠檬 - 博客园 Sourcetrail Sourcetrail 是一个开源且免费的源码阅读工具,以其强大的代码导航、可视化及跨平台支持特性,成为开发者理解复杂代码库的得力助手。…...
【蓝桥杯——物联网设计与开发】系列前言
前言 本系列博客是博主为准备2024年第十五届蓝桥杯大赛物联网设计与开发赛道而写,经过4个月学习备战,最终获得全国一等奖。 从第十六届蓝桥杯大赛开始,物联网赛道更换竞赛实训平台。之前的博客,可以借鉴代码思想,但引脚…...

【Java基础】02.Java数据类型
目录 Java 数据类型 3.1 java程序中 “” 号的使用 3.2 java中的数据类型 3.2.1 基本数据类型:数值型 (1)整数类型 (2)浮点(小数)类型 3.2.2 基本数据类型:字符型 3.2.3 基本…...

Python爬虫(一)- Requests 安装与基本使用教程
文章目录 前言一、简介及安装1. 简介2. 安装 Requests2.1 安装2.2 检查安装是否成功 二、使用 Requests 发送 HTTP 请求1. 发送 GET 请求2. 发送 POST 请求3. 发送 PUT 请求4. 发送 DELETE 请求5. 发送 HEAD 请求6. 发送 OPTIONS 请求 三、传递参数1. GET 请求传递 URL 参数1.1…...
线段树保姆级教程
买水果 Description 水果姐今天心情不错,来到了水果街。 水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。 学过oi的水果姐迅速发现了一个赚钱的方法:…...

logback之自定义过滤器
logback有两种过滤器,一种是context中的过滤器叫TurboFilter,是一个全局的过滤器,会影响所有的日志记录。另一种是Appender中的过滤器,只对所在的append有效。两者大同小异,这里我们以Appender的过滤器为例。 &#x…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...