写写Makefile

来写Makefile吧

一些小程序可能使用Makefile就足够了,比如只有几个源文件的C++程序,使用CMake可能有点杀鸡用牛刀,直接g++又会重复输入,所以写个Makefile比较省心

命名:makefile Makefile

Makefile书写规则

目标...:依赖...
	命令(shell命令)
	....
	....
	#目标是最终要生成的文件,依赖是生成目标所需的文件或目标,命令前必须Tab缩进
demo1:sub.c div.c add.c main.c mult.c
        gcc sub.c add.c div.c main.c mult.c -o demo1

image

root@ziggy-virtual-machine:~/learn_Makefile# ./demo1 
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667

Makefile工作原理

一个Makefile文件中可以有多条规则

在执行规则之前,会先检查依赖项是否存在

如果依赖项不存在且前面的规则使用了依赖项,则会向下查找其他规则

demo1:sub.o div.o add.o main.o mult.o
	gcc sub.o add.o div.o main.o mult.o -o demo1
sub.o:sub.c
	gcc -c sub.c -o sub.o
add.o:add.c
	gcc -c add.c -o add.o
mult.o:mult.c
	gcc -c mult.c -o mult.o
main.o:main.c
	gcc -c main.c -o main.o
div.o:div.c
	gcc -c div.c -o div.o
root@ziggy-virtual-machine:~/learn_Makefile# make
gcc -c sub.c -o sub.o
gcc -c div.c -o div.o
gcc -c add.c -o add.o
gcc -c main.c -o main.o
gcc -c mult.c -o mult.o
gcc sub.o add.o div.o main.o mult.o -o demo1

我们的规则书写一般都是为第一条规则来服务(Makefile自身默认执行第一条规则,如果下面的规则和第一条没啥关系,则不会执行)

Makefile会检测依赖和目标文件的更新

检测目标文件和依赖的新旧程度,如果依赖比目标文件早,则make不会重新执行内容

root@ziggy-virtual-machine:~/learn_Makefile# make
make: 'demo1' is up to date.

这样,我们写的第二个版本的Makefile更好,因为如果单独修改了某几个依赖,它不会将所有的依赖都重新编译

更完善的Makefile

用自定义变量和预定义变量简化Makefile

一大堆规则,过于繁琐也不好修改

幸亏Makefile有自定义变量:变量名:变量值

预定义变量

AR:默认值为ar 使用ar rc生成静态库文件
CC:默认cc
CXX:默认g++
$@:目标的完整名称
$<:第一个依赖文件的名字
$^:所有有依赖文件
app:main.c a.c b.c
	gcc -c main.c a.c b.c

上面的Makefile可以替换为:

app:main.c a.c b.c
	$(CC) -c $^ -o $@

在shell命令中的make选型也可以:make CC=arm-linux-gcc这样会将Makefile中所有CC变量的默认值cc替换为arm-linux-gcc

#自定义变量
src=sub.o div.o add.o main.o mult.o
target=demo2
$(target):$(src)
	$(CC) $(src) -o $(target)
sub.o:sub.c
	gcc -c sub.c -o sub.o
add.o:add.c
	gcc -c add.c -o add.o
mult.o:mult.c
	gcc -c mult.c -o mult.o
main.o:main.c
	gcc -c main.c -o main.o
div.o:div.c
	gcc -c div.c -o div.o

image

使用通配符

%

src=sub.o div.o add.o main.o mult.o
target=demo3
$(target):$(src)
	$(CC) $(src) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@

上面Makefile中,每个依赖文件都会去匹配第二条规则

image

自动获取依赖文件列表

$(wildcard [file_pattern])
#[]中的是某个或多个目录下对应的某种类型的文件
#使用例子:
$(wildcard *.c /root/newc/*.c)
#返回值为:xx.c xxx.c x.c
#由于我们需要的是.o文件名,所以需要将.c文件名批量替换,使用:
$(patsubst %.c, %.o, $(src))
#格式:$(patsubst <file_pattern>, <replace>, <text>)

作用为查找text种的单词(以空格,Tab或回车分隔)如果匹配file_pattern的格式,则以replace格式替换

此函数返回被替换后的字符串,即为我们需要的依赖文件名列表

如果前两者都有%,则replace中的%将是pattern中%所代表的字符串

%可以用'\'转义,来表示真实的%

src=$(wildcard *.c)
srco=$(patsubst %.c, %.o, $(src))
target=demo5
$(target):$(srco)
	$(CC) $(srco) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@

image

src=$(wildcard *.c)
srco=$(patsubst %.c, %.o, $(src))
target=demo5
$(target):$(srco)
	$(CC) $(srco) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@
clean:
	rm $(srco) -f

image

make clean

src=$(wildcard *.c)
srco=$(patsubst %.c, %.o, $(src))
target=demo5
$(target):$(srco)
	$(CC) $(srco) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@
	#clean是没有依赖文件的,为了防止目录中有clean文件,所以我们使用伪目标

.PHONY:clean
clean:
	rm $(srco) -f

image

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值