Linux基础——makefile编写
Makefile基本原则和原理makefile中的三要素:目标、依赖、命令目标:要生成的目标文件(在Makefile中会把第一个目标作为终极目标,一切以生成终极目标为最终目的)依赖:生成目标文件需要的一些文件命令:借助依赖文件生成目标文件的手段工作原理:要生成终极目标,先检查依赖条件是否都具备,如果有依赖条件不存才则再寻找新的规则来生成依赖条件Makefile的...
·
Makefile基本原则和原理
makefile中的三要素:目标、依赖、命令
目标:要生成的目标文件(在Makefile中会把第一个目标作为终极目标,一切以生成终极目标为最终目的)
依赖:生成目标文件需要的一些文件
命令:借助依赖文件生成目标文件的手段
工作原理:要生成终极目标,先检查依赖条件是否都具备,如果有依赖条件不存才则再寻找新的规则来生成依赖条件
Makefile的编写
Makefile文件命名为makefile或Makefile
第一种形式
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版本就成型了!!
更多推荐
已为社区贡献1条内容
所有评论(0)