关于 Makefile,如何编写成型文件

工作原理:要生成终极目标,先检查依赖条件是否都具备,如果有依赖条件不存才则再寻找新的规则来生成依赖条件

Makefile的编写
Makefile文件命名为makefile或Makefile
第一种形式

app:main.c insert_sort.c select_sort.c
    gcc *.c -o app -std=c99

直接使用命令生成目标文件,但是只要更新了其中的一个文件,所有文件都需要重新编译,大大浪费了时间

app:main.c insert_sort.c select_sort.c
    gcc *.c -o app -std=c99

直接使用命令生成目标文件,但是只要更新了其中的一个文件,所有文件都需要重新编译,大大浪费了时间

第二种形式

app:main.o insert_sort.o select_sort.o
    gcc main.o insert_sort.o select_sort.o -o app

main.o:main.c
    gcc main.c -c -std=c99

insert_sort.o:insert_sort.c
    gcc insert_sort.c -c -std=c99

select_sort.o:select_sort.c
    gcc select_sort.c -c -std=c99

先生成.o文件再生成目标文件,采用链式的方法可以大大节省时间,当其中一个文件发生改变时,只用重新编译更新文件

第三种形式
可以看出第二种形式虽然解决了第一种方式中存在的问题,但代码显得非常冗余,而且可维护性差,我们可以借助makefile中的变量来进一步进行修改。

makefile中的变量分为普通变量和自动变量。
普通变量:普通变量可以用户自己定义也可以使用Linux维护的一些变量。
变量定义及赋值:obj = a.o b.o c.o
变量取值:$(obj)
由Linux系统维护的一些变量通常为大写,常见的如下所示:
CC:默认值 cc
CPPFLAGS : 预处理器需要的选项 如:-I
CFLAGS:编译的时候使用的参数 –Wall –g -c
LDFLAGS :链接库使用的选项 –L -l

自动变量:
$@:规则中的目标
$<:规则中的第一个依赖条件
$^:规则中的所有依赖条件
注:上述三种自动变量只能在命令中使用

模式规则:
makefile中提供了模式规则匹配
%.o:%.c
其中%表示一个或多个

代码:
target = app
obj = main.o insert_sort.o select_sort.o
CC = gcc
CFLAGS = -std=c99

$(target):$(obj)
    $(CC) $(obj) -o $(target)

%.o:%.c
    $(CC) $< -c $(CFLAGS)

现在的版本看起来已经完全不一样了,几乎没有一点之前的影子,而且也显得非常简洁。但是我们仔细观察可以发现,虽然引用了变量,但是再给变量赋值时仍然需要列出所有的依赖文件,如果文件有成百上千个,就会带来很大的麻烦!!


第四种形式

在makefile中提供了函数功能来解决上述的问题,makefile中所有的函数必须都有返回值,下面介绍几种常用的函数

wildcard:查找指定目录下指定类型的文件,一个参数
用法:src = $(wildcard ./src/*.c)
注:在makefile的函数中,函数的调用方式为  函数名 参数1,参数2,参数3....

patsubst:匹配替换,从src中找到所有某种格式的文件换成另一种格式
obj = $(patsubst %.c,%.o,$(src))

代码:
target = app
CC = gcc
CFLAGS = -std=c99
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))

$(target):$(obj)
    $(CC) $(obj) -o $(target)

%.o:%.c
    $(CC) $< -c $(CFLAGS)

这样整个代码就变得非常整洁、易维护了。但是如果我们想重新编译,删除.o文件,就必须手动删除,有没有办法可以使用makefile一键清空呢?


第五种形式

target = app
CC = gcc
CFLAGS = -std=c99
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))

$(target):$(obj)
    $(CC) $(obj) -o $(target)

%.o:%.c
    $(CC) $< -c $(CFLAGS)

.PHONY:clean  
clean:
    rm $(target) $(obj) -f

这里我们添加一个clean目标,我们发现这个目标没有依赖条件,我们称这样的目标为伪目标,并使用.PHONY来声明。

声明它为伪目标的原因是,如果在当前目录下碰巧有一个文件名也叫clean,就会发生冲突,执行make clean时就会提示你clean目标已经处于最新状态。

后面的-f参数表示强制执行该条命令,来清除报错。

这样一个非常实用的makefile版本就成型了!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值