Makefile基础入门

Makefile介绍

Makefile是一种强大的工程管理编译工具,对于一个大型的工程来说,其按照类型、功能、模块等放在不同的路径下,makefile定义了一些规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于更复杂的操作,其也可以执行操作系统的命令

Makefile规则

用一句话来说,其实就是:
目标文件:依赖文件
TAB键 命令
运行规则为:当我的依赖比我的目标新或者目标不存在的时候,就执行这个命令。否则不执行这个命令。

示例

假如说我现在有两个文件,分别为a.c和b.c,程序如下:
a.c程序:

#include<stdio.h>

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

b.c程序:

#include<stdio.h>

void func_b(void)
{
	printf("This is a Test Demo -- File B.\n");
}

我们可以使用gcc对这个小Demo进行编译,假如我们生成的可执行文件为test,则需要经历以下几个步骤:

1.gcc -c -o a.o a.c
2.gcc -c -o b.o b.c
3.gcc -o test a.o b.o

设想一下,我们的程序可能不止两个源文件,可能成百上千个,我们每一次编译生成的可执行文件也不一定都是正确的结果,每次生成可执行文件都需要至少三个步骤,可见这是多么低下的效率。这时候Makefile就可以派上用场了。我们可以将这些编译规则写入一个名为Makefile的文件中,写法如下:

test:a.o b.o                   //test的生成需要依赖于a.o和b.o文件
	gcc -o test a.o b.o    //生成test的命令
a.o:a.c                         //a.o的生成需要依赖于a.c文件
	gcc -c -o a.o a.c
b.o:b.c                        //b.o的生成需要依赖于b.c文件
	gcc -c -o b.o b.c

改进

写完之后我们发现,对于当前的这个程序,我们确实可以用这个Makefile进行编译,但如果我现在需要增加c.c文件呢?我是不是需要在Makefile里边对新的文件添加编译规则了;如果我增加了许多源文件呢?显然这种方式并不是最好的方式,通用性还是不够,接下来我们需要改进它。使它的通用性很强,这样Makefile编写一次就不再需要大改,而是小修小补。
先贴出改进的Makefile,如下所示:

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

我的c.c如下:

#include<stdio.h>

void func_c(void)
{
	printf("This is a Test Demo -- File C.\n");
}

a.c此时修改如下:

#include<stdio.h>

int main()
{
	func_b();
	func_c();
	return 0;
}

其中:

  • $^ 表示所有的依赖文件
  • $@ 表示目标文件
  • $< 表示第一个依赖
    这样就是一个通用性比较强的Makefile了,如果我增加文件,只需写出文件编译过后的.o文件作为test的依赖即可。但这种改进的Makefile并不是最简洁的形式,但对于新人理解使用Makefile已经足够。
    我在使用Makefile过程中,除了最终的可执行文件,还会生成许多的中间文件,所以我们可以使用一些清除操作,在Makefile 文件中编写如下代码:
test:a.o b.o c.o
	gcc -o test $^
%.o:%.c
	gcc -c -o $@ $<
clean:
	rm *.o test
.PHONY:  clean

rm 是linux 的一个系统操作指令,意思是执行删除文件、文件夹等操作。*.o 代表所有的以.o为结尾的文件。为什么要写.PHONY ,它的意思是.PHONY后边为一个假想的目标,因为我们在clean这些文件的时候需要执行make clean命令,如果不写这句话,有时候会出问题,比如这时候我文件名中刚好有一个叫clean名字的文件,那么执行这句话就会有问题,其会编译clean文件而不是清除中间文件和test。

Makefile其他常用语法

即时变量、延时变量

  • := 即时变量,例如:A:= xxx ,代表A的值可以立即确定,在A定义的时候就确定。
  • = 延时变量,例如:B=xxx,代表B的值在其使用到的时候才确定。
  • ?= 延时变量,若是第一次定义才有效,若在之前定义,则无效(即代表忽略此句)。
  • += 附加,它是即时变量还是延时变量取决于之前的语句。

Makefile函数

  • $(wildcard pattern)
    #意思是在pattern中定义你需要寻找的文件格式,wildcard取出当前路径中存在的 相关文件。
    例如:$(wildcard *.c) – 取出当前路径下.c为后缀名的文件,并用分号隔开。
  • $(subst FROM,TO,TEXT)
    #意思是将TEXT中的东西从FROM变成TO,FROM为我要替换的文件或形式,TO为我要替换成的形式。
    例如:$(subst a,the,There is a cat) – 将There is a cat中的a替换成the。
  • $(foreach var,list,text)$(filter pattern...,text)
    #意思是从text中取出适合pattern格式的值。
    例如:
A = a b c d/
B = $(filter %/, $(A))   #可以从A的a b c d/中取出d/

filter的另一种函数形式为:
$(filter-out pattern..., text)
#意思是从text中取出不符合pattern类型的值。例如上边的语句改为:
B = $(filter-out %/, $(A))则代表取出不符合%/格式的数据,结果为a b c

更多参考

就写到这里吧,这只是一个关于Makefile的简单实用的例子,其中Makefile的规则和语法还有很多,感兴趣的小伙伴可以去GNU make的官网下载阅读,我也把链接粘贴在这里,希望能跟各位小伙伴多多交流。
链接:GNU Make PDF下载

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值