嵌入式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 %/, (filterout©)
功能:在变量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能有帮助!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacky~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值