IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 嵌入式Linux应用开发(二)——Makefile引入 -> 正文阅读

[系统运维]嵌入式Linux应用开发(二)——Makefile引入


一、Makefile的引入

Makefile的介绍:Makefile是一个编译辅助器,并不是编译器。它只是提供辅助我们进行编译的一个工具。就像一个Shell脚本一样来通过执行一些命令,来实现某些操作。

Makefile的引入:在Linux没有像我们的Windows上比如VS,CLion,等这些方便的图形化编译软件,那我们怎么编译呢?在Linux上我们通过命令行

gcc -o xxx  xxx.c  xxx.c

来对文件进行编译,但是我们在这个过程中发现,如果文件很多,而且我们还需要多次编译来进行调试,那岂不是要敲这样的指令很多次,岂不是麻烦的要死。正因如此,Makefile就诞生了。
(见下展示,实际调试)
Makefile的功能:给大家一个背景(在有成千上完个文件需要我们进行编译,在你没有接触Makefile之前,那就通过gcc -o xxx xxx这样把所有的编译一下,但是突然你发现,我有个文件的某个地方有个小错误,难道我就用这个值再来一遍?是不是显得太过于麻烦了!!!)。因此为了方便我们进行文件的编译。

展示

这是两个非常简单的代码a.c b.c
a.c

#include<stdio.h>

int main(){
    fun();
    return 0;
}

b.c

#include<stdio.h>

void fun(){
    printf("This is B!\n");
    return;
}

编译结果

在这里插入图片描述

结果分析

上面的警告可以不用管,这个指令的过程是编译a.c 和b.c生成 一个build的可执行文件。a调用了b的函数,所以生成了这个build实际上是在编译a.c 和 b.c的时候,生成了a.o和b.o最后通过链接才生成了可执行文件build。可以通过指令(对这个过程不懂的,推荐去看一下(一))

在这里插入图片描述

二、Makefile的使用

相信通过上面的介绍,你对Makefile也有了一个清晰的认识,至少当别人问起你的时候,你能清楚的向他人介绍起Makefile。那么下面我们就开始对Makefile的使用进行分析

1.Makefile的规则

Makefile的规则可以归纳为如下
在这里插入图片描述一个目标文件可以有多个依赖
比如我们上一个例子我们可以进行细分
目标文件build: 通过

gcc -o build a.o b.o

链接生成

而依赖文件a.o通过

gcc -c -o a.o a.c 

编译生成

依赖文件b.o通过

gcc -c -o b.o b.c 

编译生成

因此我们可以简单的写出一个Makefile如下

build:a.o b.o
	gcc -o build a.o b.o
a.o:a.c
	gcc -c -o a.o a.c
b.o:b.c
	gcc -c -o b.o b.c

在Linux上运行一下
在这里插入图片描述可以看出,通过编写这样的一个Makefile文件就能达到我们的效果,但是我再make一下,系统就提示,build已经是最新的了,所以不需要再编译,就用原来那个就行。(这就是Makefile的原理)

Makefile的原理:通过比较目标文件和依赖文件的时间,如果目标文件不存在,表明需要对文件进行编译,生成新的文件。如果依赖文件进行了修改,表明需要重新编译依赖文件。(比如a.c进行了修改,那么通过比较a.o和a.c的最后修改时间发现,a.c比a.o新,所以我们就需要重新编译一下a.c。自然a.o更新了,build同理也要更新。但是b.c,b.o从始至终都没有更新过,所以他们两个自然就不需要进行再次编译)这就是Makefile的工作原理


2.Makefile的语法

对于嵌入式应用开发来说,我们只需要掌握基本的Makefile操作就行,下面我们就对Makefile的基本语法进行分析。

2.1 通配符 %

对比上面的Makefile,我们可以进行如下的修改,同时也添加了c.c
c.c

#include <stdio.h>

void fun_c(){
    printf("This is C!\n");
    return;
}

Makefile

build:a.o b.o c.o
	gcc -o build $^
%.o:%.c
	gcc -c -o $@ $<

运行结果:
在这里插入图片描述分析:
当我们需要生成目标文件build的时候,需要依赖文件a.o,b.o,c.o。因此程序会自动地向下去找,发现了
在这里插入图片描述这样地一个规则可以来生成我们的a.o ,b.o c.o。
%:表示通配符
$@:表示目标文件
$<:表示第一个依赖文件(从左到右)
$^:表示所有的依赖文件

2.2 假想目标 .PHONY

为什么需要假想目标呢?
比如我们需要删除期间生成的a.o,b.o,c.o。那我们就只需要改一下Make file如下

build:a.o b.o c.o
	gcc -o build $^
%.o:%.c
	gcc -c -o $@ $<

clean:
	rm  *.o build

然后在终端上执行如下
在这里插入图片描述所以我们就成功删除了不想要的文件。
为什么要加clean呢?
因为如果你执行make,他会默认执行生成你的第一个目标文件,加一个clean。就表示你要生成的目标文件(如果文件不存在就执行下面的代码——Makefile的规则嘛)。

但是,此时你想如果文件内已经有这个clean文件了怎么办?他还会执行吗?如下
在这里插入图片描述因为系统发现,clean文件已经是最新的了,所以就不会执行后面的指令。因此,我们就无法删除那些我们不需要的文件。

为了解决这样的一个文件,我们就需要使用假想目标,只需要更改一下代码,如下

build:a.o b.o c.o
	gcc -o build $^
%.o:%.c
	gcc -c -o $@ $<

clean:
	rm  *.o build
.PHONY:clean

结果
在这里插入图片描述所以即使有这个文件也不影响我们执行clean下面的指令。(系统会假想没有这个文件)

2.3 变量

在这里插入图片描述A:=xxxx (表示的是这是一个即时变量,就是说这个值已经确定)
B = xxx (表示的是这是一个延时变量,只会在你使用到他的时候,他的值才确定 验证如是实验一)

?= (表示延时变量,区别是只会在第一次定义时才会起作用,如果前已经定义了,就忽略掉)

+= (表示附加,类型取决于前面是怎么定义的,验证如实验二)

实验一
编写Makefile如下

A :=$(C)
B = $(C)
C=123
all:
	@echo A=$(A)
	@echo B=$(B)


运行结果:
在这里插入图片描述分析:因为最开始的时候,C的值为NULL,因此A此时赋值的结果就是NULL。而B是使用的时候,会去在程序中找,C的值,因此B的值就是123

实验二
更改Makefile如下

A :=$(C)
B = $(C)
C=123

all:
	@echo A=$(A)
	@echo B=$(B)

B+=456
B?=789

运行结果:
在这里插入图片描述
分析:如果你把B?=789放在声明B的前面且后面不对B进行赋值(因为你再赋值就会覆盖掉前面的值),那么结果就如下·所示
在这里插入图片描述


3.Makefile函数

对于Makefile函数下面主要介绍4个函数。对于函数不熟悉,建议参考文档
http://www.gnu.org/software/make/manual/

3.1 $foreach()函数

$(foreach f , $(A), $(f) . o)
这个函数的功能:就是将变量A中的值执行函数f(即替换为.o)

3.2 $filter()函数

$ (filter %/, $?)
功能:在变量C中查找%/格式的元素

3.3 $filter-out()函数

( f i l t e r ? o u t (filter-out %/, (filter?out?)
功能:在变量C中查找不符合%/格式的元素

3.4 $wildcard()函数

$(wildcard *.c)
功能:查找当前目录中真实存在的文件

3.5 $patsubst()函数

$ (patsubst %.c ,%.d, $(file2))
功能:将变量file2中%.c格式的元素 替换为 %.d格式

Makefile代码:

A :=a b c
B = $(foreach f ,$(A),$(f).0)

C=a b c d/
D=$(filter %/,$(C))
E=$(filter-out %/,$(C))

files=$(wildcard *.c)

file2=a.c b.c c.c d.c e.c abc
file3=$(wildcard &(file2))

dep_file=$(patsubst %.c,%.d,$(file2))

all:
	@echo B=$(B)
	@echo D=$(D)
	@echo E=$(E)
	@echo files=$(files)
	@echo file3=$(file3)
	@echo dep_file=$(dep_file)

在这里插入图片描述


总结

希望上面的介绍和实验对你了解熟悉Makefile能有帮助!

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 18:06:28  更:2021-12-01 18:08:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 2:43:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码