网站域名查企业邮箱,济南谷歌推广,企业网络推广方案怎么做,长春网站制作都找源晟27文章目录 一、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… 文章目录 一、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 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 --apcsinterwork --split_sections -I.\RTE\_led_c -IC:\Users\thisway_diy\AppData\Local\Arm\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include -IC:\Keil_v5\ARM\CMSIS\Include -D__UVISION_VERSION527 -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 --apcsinterwork -I.\RTE\_led_c -IC:\Users\thisway_diy\AppData\Local\Arm\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include -IC:\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.axf1.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.hint 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) (1x) 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.o2.使用后缀名决定编译过程
参考《嵌入式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