当前位置: 首页 > article >正文

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命令行执行命令的话
      不需要加双引号
  • 在某个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 _DEBUG
    printf("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

http://www.kler.cn/a/463110.html

相关文章:

  • 除了淘宝、天猫和京东,其他电商平台的按图搜索商品API返回值结构是怎样的?
  • 计算机网络•自顶向下方法:网络层介绍、路由器的组成
  • BP神经网络的反向传播算法
  • Unity UGUI使用技巧与经验总结(不定期更新)
  • 基于深度学习算法的AI图像视觉检测
  • Node 如何生成 RSA 公钥私钥对
  • 用PicGo向Github图床上传图片,然后通过markdown语言显示图片
  • Qt天气预报系统设计界面布局第四部分左边
  • 基于单片机中药存放环境监测系统的实现
  • 第三讲 比特币的早期发展
  • overscroll-behavior-解决H5在ios上过度滚动的默认行为
  • 茶叶连锁店管理系统(源码+文档+部署+讲解)
  • MySQL三大日志(binlog、redo log和undo log)详解
  • 职场常用Excel基础01-数据验证
  • LVGL部件篇: 开关部件(lv_switch)
  • 电商数据API接口的稳定性保障与性能优化策略
  • AI as a Platform (AIaaP) for Enterprises — 发展与转型
  • Go信号处理:如何优雅地关闭你的应用
  • 论文略读: Scaling laws with vocabulary: larger model deserve larger vocabularies
  • 科伦川宁生物:绿色科技引领,双翼齐飞筑梦未来
  • 深入聊聊typescript、ES6和JavaScript的关系与前瞻技术发展
  • 数据仓库中的指标体系模型介绍
  • nginx学习之路-windows系统安装nginx
  • 自学记录:学习HarmonyOS Location Kit构建智能定位服务
  • 【开源免费】基于SpringBoot+Vue.JS精准扶贫管理系统(JAVA毕业设计)
  • windows文件夹自定义右键调用powershell完成7zip加密打包