编译原理

编译工具将我们的源码文件最终编译成可执行文件,并不是一步到位的,其中要经过一个类似工厂流水线的过程,交叉编译工具中包含负责处理各个环节的功能工具,所以叫做交叉编译工具链。

编译的一般过程分为:

预编译->编译->汇编->链接->生成 elf 文件->转换为二进制可支持 bin 文件。

预编译 Pre-compile 阶段:主要是对头文件#include 、宏定义#define 等进行展开。

编译 compile 阶段:主要是将我们的.c 文件编译成汇编.s 文件。

汇编 Assembly 阶段:将汇编文件.s 编译成为目标文件.o。

链接 Link 阶段:将生成.o 文件链接生成.elf 文件。

转换阶段:将生成的.elf 文件转换成为可执行二进制.bin 文件。

而这些编译步骤是通过 make 工具解析 Makefile 文件来执行。Makefile 文件中描述了整个工程所有文件的编译顺序、编译规则、依赖关系等。

MAKEFILE

前面我们提到过,Make 工具通过解析 Makefile 文件进行一系列编译操作,最终生成我们想要的镜像文件。Makefile 文件中描述了个工程所有文件的编译顺序、编译规则以及依赖关系,决定了工程中文件是否需要编译,以及这些文件的编译顺序。Make 工具还可以通过比较文件最后修改时间,来决定哪些文件需要更新哪些不需要更新,更改了某个文件之后,只对依赖此文件的目标文件进行重新编译更新,这就大大减少了编译时间。

打开源码目录可以看到,Makefile 文件不仅存在于源码根目录下,在其他的子目录下也基本都有

Makefile 文件。在执行编译时,Make 工具会解析根目录下 Makefile 文件进行编译,而根目录的 Makefile会调用子目录下的 Makefile,子目录下又有子目录,层层调用。

Makefile 需要按照一定的格式语法规则进行书写。如果你是做 Linux 应用开发的人员,那么写 Makefile就是必备技能,就需要深谙 Makefile 语法规则。对于我们 Linux 平台初级开发人员,很少需要我们去写一个复杂的 Makefile 文件,只是在做平台移植的时候可能需要去简单修改或者阅读 Makefile 文件。

下面我们就简单了解一下 Makefile 基本格式规则。

1 、 目标和依赖

目标就是我们需要生成文件,依赖就是生成目标文件所需要的其他文件,称为依赖文件。基本语法规则如下:

targets … :dependent_files …(tap)command…

举例一:我们先创建一个简单的 app.c 文件。

forlinx@ubuntu:~/work/tmp$ touch app.c

在文件中输入如下代码

#include <stdio.h>int main(void){printf("my first app !!! \r\n");return 0;}

按照基本规则建立一个简单的 Makefile 文件,app 为我们需要的目标文件,app.c 为所要生成的 app 的依赖文件,gcc –o app app.c 就是生成目标 app 需要执行的命令。

建立一个 Makefile 文件:

forlinx@ubuntu:~/work/tmp$ touch makefile

文件中输入如下内容:

app:app.cgcc -o app app.c

使用 make 命令,可以看到执行了命令 gcc -o app app.c,ls 命令查看文件,发现在该目录下生成了app 目标文件:

forlinx@ubuntu:~/work/tmp$ make

执行 app,即可看到 app.c 中我们写的打印信息:

forlinx@ubuntu:—/work/tmpS ./app my first app !! ! forlinx@ubuntu:—/work/tmpS 

然后我们再执行 make 命令,会发现出现如下信息,’app’ is up to date,说明 app 已经是最新的,没必要再重新生成:

forunx@ubuntu:—/work/tmpS
up to date.
app' is
forunx@ubuntu:—/work/tmpS
make 

我们做一下稍微的改动,修改 app.c 文件中的内容或者使用 touch 命令更改一下 app.c 的时间属性,然后再进行 make 看看:

forunx@ubuntu:—/work/tmpS touch app.C
forunx@ubuntu:—/work/tmpS make
gCC 一 0 app app•C
forunx@ubuntu:—/work/tmpS 

可以看到又重新执行了 gcc -o app app.c 命令,重新生成了 app。也就是说,make 工具会判断依赖

文件的 时间戳 是否比目标文件时间戳更新, 来决定是否重新生成目标文件。

我们再举一例:

假如我们有多个文件需要编译,比如我们创建多个文件 fun1.c,fun1.h,fun2.c,fun2.h,app.c。

fun1.c:#include <stdio.h>#include "fun1.h"void fun1(char *s){printf("%s\r\n",s);}fun1.h:#ifndef _FUN1_H#define _FUN1_Hvoid fun1(char *s);#endiffun2.c#include "fun2.h"int fun2(int x,int y){return x+y;}fun2.h#ifndef _FUN2_H#define _FUN2_Hint fun2(int x,int y);#endif

创建 app.c 文件,该文件引用 fun1.c 和 fun2.c 中定义的函数。

#include <stdio.h>#include "fun1.h"#include "fun2.h"int main(void){fun1("I am fun1 !");printf("fun2 return value=%d \n",fun2(1,2));return 0;}

最后创建 makefile 文件,其中 app 是我们的最终目标文件,app 的依赖文件为 app.o、fun1.o、fun2.o,

这几个.o 文件称为中间目标文件,它们又有各自所依赖的.c 和.h 文件,最后的 clean 也是一个目标文件,

但是这个目标没有任何依赖,也不会生成真正文件,只是执行一条命令,我们称之为伪目标。我们可以看

到 clean 执行的是删除.o 和 app 的命令。

app: app.o fun1.o fun2.ogcc -o app app.o fun1.o fun2.oapp.o: app.cgcc -c app.cfun1.o: fun1.c fun1.hgcc -c fun1.cfun2.o: fun2.c fun2.hgcc -c fun2.cclean:rm -rf *.o app

创建完成之后,我们直接 make:

上图可以看到生成最终目标 app 和一些中间目标文件,这个过程经过了以下四个步骤:

gcc -c app.c

gcc -c fun1.c

gcc -c fun2.c

gcc -o app app.o fun1.o fun2.o

执行 app,可以看到执行成功:

现在修改其中一个文件 fun2.h 后,比如更改一下 fun2.h 的时间属性,然后再次编译:

可以看到只用了两个步骤,app 的其他依赖文件并没有被重新编译生成。

最后,执行 make clean 清除中间文件和 app:

嵌入式学习笔记之一:嵌入式linux中混合编译入门相关推荐

  1. 运维学习笔记10补充——Linux中的网桥设置

    先删除已有网桥,恢复默认的网卡设置. 此时主机只剩下一个ifcfg配置文件,对其进行更改 注意:decice的设备名称为真实存在设备名称,每台主机不同,需要用ifconfig查看 设置完成后保存,然后 ...

  2. 嵌入式开发学习笔记5-了解单片机中的特殊功能寄存器(寄存器B、累加器A和程序状态字PSW)

    嵌入式开发学习笔记5-了解单片机中的特殊功能寄存器(寄存器.累加器和程序状态字) 累加器A 寄存器B 程序状态字PSW 累加器A 累加器A是ACC(Accumulator)的缩写,累加器A是一个具有特 ...

  3. 嵌入式开发学习笔记6-了解单片机中的特殊功能寄存器(定时器/计数器)

    嵌入式开发学习笔记6-了解单片机中的特殊功能寄存器(定时器/计数器) 定时器/计数器简介 TH与TL TMOD工作模式寄存器 TCON定时器控制寄存器 定时器操作实例 定时器/计数器简介 在单片机中, ...

  4. 嵌入式学习笔记--misc

    嵌入式学习笔记–misc 一.内核自带MISC驱动简介 misc 的意思是混合.杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动. ...

  5. 嵌入式学习笔记——ADC模数转换器

    ADC模数转换器 前言 ADC介绍 ADC概述 ADC的数量 ADC的特性 ADC框图 芯片外部框图 芯片内部框图 转换部分框图 状态输出部分 条件触发框图 寄存器介绍 编程思路 模式选择 规则通道的 ...

  6. cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)

    cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断) https://blog.csdn.net/qq_16255321/article/details/43086 ...

  7. 嵌入式学习笔记——STM32的USART通信概述

    文章目录 前言 常用通信协议分类及其特征介绍 通信协议 通信协议分类 1.同步异步通信 2.全双工/半双工/单工 3.现场总线/板级总线 4. 串行/并行通信 5. 有线通信.无线通信 STM32通信 ...

  8. 嵌入式学习笔记--jlink 工具RTT使用笔记

    嵌入式学习笔记–jlink 工具RTT 使用笔记 最近有调试一个ethcat板卡的需求,板卡设计的很简洁,没有多余的调试串口,正准备飞线到单片机针脚上的时候发现了RTT 的这个工具,记录一下使用的方法 ...

  9. 基于STM32G431嵌入式学习笔记——七、定时器定时

    一.题目引入 上述为第13届蓝桥杯省赛节选内容,为了研究定时器的机理并独立书写计时函数,上述内容简化为以下要求: ①按下B4按键,LD1点亮5s后熄灭 ②按下B3按键,LD2以0.1秒为间隔切换亮灭状 ...

最新文章

  1. 怎样向IT行业的朋友说明《圣经》的重要性
  2. 计算机网络数据容量100M,华工网络教育计算机网络作业及答案
  3. python3怎么创建一个链表_怎么创建一个自己的微信公众号
  4. django drf Filter
  5. JAVAEE联邦软件管理系统试题
  6. python 将列表中的字符串转为数字_python 将列表中的字符串转为数字
  7. 王俊和尹玉新团队合作开发代谢组联合人工智能肺癌早期检测新方法
  8. Android应用程序与SurfaceFlinger服务的连接过程分析
  9. 函数的动态参数和作用域
  10. 1682. [HAOI2014]贴海报
  11. SQL 面试题及答案(一)
  12. python实现列表的排列和组合
  13. tcpserver检测断开qt_QTcpServer或QTcpClient(在服务器端)知道,已连接的客户端现已断开连接...
  14. 变废为宝,用旧电脑自己DIY组建 NAS 服务器
  15. fst和skiplist
  16. 计算机英语单词怎么巧背,巧计英语单词的26个秘诀
  17. PHP ThinkPHP 命名空间引入(use )
  18. 计算机组装在线作业_1,中石油华东《计算机维护技术》2018年秋学期在线作业(三).doc...
  19. 【论文笔记】ARBITRAR: User-Guided API Misuse Detection
  20. 坚持平凡 创造非凡

热门文章

  1. Confluence 6 如何配置快速导航的同时查找数量
  2. RabbitMQ Java 基本API
  3. 20180320作业1:源代码管理工具调查
  4. 神器:REST测试工具[wiztools.org restclient]客户端Jar依赖Java安装环境
  5. vue2.0 与 bootstrap datetimepicker的结合使用
  6. Source Insight 基本使用(1)-使用Source Insight查看Android Framework 源码
  7. 不插即用!配备微信网页授权模块的CodeIgniter应用脚手架
  8. mvc3 RenderAction传参问题
  9. 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记20 Multiple MVCs 多MVC模式、NavigationController导航控制器...
  10. Android UI开发详解之ActionBar .