0721Makefile的制作
2015-07-22 18:41
387 查看
用途
工作原理
版本一
版本二
引入变量
版本三
引入函数
版本四
版本五
节省编译项目的时间
根据一览关系自底向上执行命令
根据修改时间比较目标新旧,确定更新
如果目标不依赖任何条件,则执行对应命令,以示更新
目录结构
.
├── a.c
├── b.c
├── c.c
├── d.c
├── calc.h
└── main.c
制作Makefile文件
Makefile语法规则:三要素:目标、依赖、命令
在上列命令中
保存之后,直接运行make命令,执行过程如下:
执行结果,生成app的可执行文件,和a.out一样,
三要素解析:
格式:命令顶格写,要加冒号
当Makefile开始执行的时候,会形成一个类似上图的树状依赖关系图,然后从下往上一条一条执行,生成树根的目标app
保存之后,直接运行make命令,执行过程如下:
执行结果正常运行
如果这时候,打开a.c,修改一下,加入一个行
再次执行make命令,执行过程如下:
结果是只把a.c重新编译,然后在和其他的.o文件重新链接,生成一个新的app
如果是版本一的话,所有的.c文件都要重新编译,然后链接生成文件,浪费时间,这就是版本二的优势,提高编译效率
那make是如何得知a.c被更改了呢?是根据a.c和app的时间决定的,如果a.c的修改时间新于目标app的时间,那就会重新编译、链接。
如果把Makefile的内容改为
再次执行make命令,执行过程如下:
依旧执行成功,但是通过
为什么并没有设置.o的目标,但是还是过
如果把Makefile的内容改为
执行过程如下:
利用上述规则把
这条语句修改成
例子:定义一个
执行过程:
解析:
通过引入变量,在改变一下Makefile的内容
执行过程:
通过引入函数,在改变一下Makefile的内容
执行过程:
执行结果没有问题
初步完善后
当需要删除.o文件和app可执行文件的时候,可以执行
但是有一种情况,当目录下有个文件名叫做clean,这个时候执行
为了避免这中情况,需要加入一个clean的目标
现阶段的使用的Makefile
注意:用这个Makefile的时候,文件夹里不要有其他项目的.c文件。
工作原理
版本一
版本二
引入变量
版本三
引入函数
版本四
版本五
用途
项目代码编译管理节省编译项目的时间
工作原理
分析个目标文件和依赖之间的关系根据一览关系自底向上执行命令
根据修改时间比较目标新旧,确定更新
如果目标不依赖任何条件,则执行对应命令,以示更新
目录结构
.
├── a.c
├── b.c
├── c.c
├── d.c
├── calc.h
└── main.c
制作Makefile文件
版本一
`vi Makefile`创建一个Makefile文件,一般第一个M要大写,
Makefile语法规则:三要素:目标、依赖、命令
Makefile内容
app:main.c a.c b.c c.c d.c gcc main.c a.c b.c c.c d.c -o app
在上列命令中
app是目标,
main.c a.c b.c c.c d.c是依赖或者条件,
gcc main.c a.c b.c c.c d.c -o app是命令。
保存之后,直接运行make命令,执行过程如下:
$ make gcc main.c a.c b.c c.c d.c -o app
执行结果,生成app的可执行文件,和a.out一样,
./app可以成功运行。
make这条命令是默认执行当前的Makefile文件
三要素解析:
app是目标,如果要生成目标,就要依赖
main.c a.c b.c c.c d.c,如何依赖目标生成文件,就要执行命令
gcc main.c a.c b.c c.c d.c -o app。
格式:命令顶格写,要加冒号
:,依赖跟在后面,命名前面要有一个tab制表符的间隔。
版本二
Makefile内容
app:main.o a.o b.o c.o d.o gcc gcc main.o a.o b.o c.o d.o -o app main.o:main.c gcc -c main.c a.o:a.c gcc -c a.c b.o:b.c gcc -c b.c c.o:c.c gcc -c c.c d.o:d.c gcc -c d.c
保存之后,直接运行make命令,执行过程如下:
$ make gcc -c main.c gcc -c a.c gcc -c b.c gcc -c c.c gcc -c d.c gcc main.o a.o b.o c.o d.o -o app
执行结果正常运行
如果这时候,打开a.c,修改一下,加入一个行
再次执行make命令,执行过程如下:
$ make gcc -c a.c gcc main.o a.o b.o c.o d.o -o app
结果是只把a.c重新编译,然后在和其他的.o文件重新链接,生成一个新的app
如果是版本一的话,所有的.c文件都要重新编译,然后链接生成文件,浪费时间,这就是版本二的优势,提高编译效率
那make是如何得知a.c被更改了呢?是根据a.c和app的时间决定的,如果a.c的修改时间新于目标app的时间,那就会重新编译、链接。
如果把Makefile的内容改为
app:main.o a.o b.o c.o d.o gcc gcc main.o a.o b.o c.o d.o -o app
再次执行make命令,执行过程如下:
$ make cc -c -o main.o main.c cc -c -o a.o a.c cc -c -o b.o b.c cc -c -o c.o c.c cc -c -o d.o d.c gcc main.o a.o b.o c.o d.o -o app
依旧执行成功,但是通过
cc编译的,通过
whih cc和
ls查看符号链接,发现
cc还是链接的
gcc
为什么并没有设置.o的目标,但是还是过
cc编译了,这是因为makefile的内置规则,通过
make -p命令查看,最好重定向到文件里,方便观察。
如果把Makefile的内容改为
app:main.o a.o b.o c.o d.o gcc main.o a.o b.o c.o d.o -o app %.o:%.c gcc -c $< -o $@
执行过程如下:
$ make gcc -c main.c gcc -c a.c gcc -c b.c gcc -c c.c gcc -c d.c gcc main.o a.o b.o c.o d.o -o app
%.o:%.c:语义是把.c文件转换成.o,如何转,执行命令。 % :相当通配符 $< :表示所有依赖当中的第一个依赖 `%.c`. $@ :表示目标`%.o` $^ :表示依赖库中的所有依赖, `main.o a.o b.o c.o d.o`
利用上述规则把
app:main.o a.o b.o c.o d.o gcc main.o a.o b.o c.o d.o -o app
这条语句修改成
app:main.o a.o b.o c.o d.o gcc $^ -o $@
引入变量
常见变量CFLAGC= LDFLAGC= CPPFLAGS=
CFLAGC=:一般指编译时传递参数 -c -g,只编译不连接
LDFLAGC=:用来指定库是在什么位置的
CPPFLAGS=:一般指编译时传递参数 -I./
例子:定义一个
test变量;把变量赋值
"hello",调用变量要用
$()的方式。
test = "hello" abc: echo $(test)
执行过程:
$ make abc echo "hello" hello
解析:
make,默认执行第一个目标,
make abc,make后面加上目标, 只执行该目标的命令;如果目标不依赖任何条件,则执行对应命令,以示更新,所以执行echo命令回显”hello”。
通过引入变量,在改变一下Makefile的内容
CFLAGC= -c -g -Wall LDFLAGC= CPPFLAGS= -I./ obj = main.o a.o b.o c.o d.o app:$(obj) gcc $^ -o $@ %.o:%.c gcc $(CFLAGC) $(CPPFLAGS) $< -o $@
执行过程:
$ make gcc -c -g -Wall -I./ main.c -o main.o gcc -c -g -Wall -I./ a.c -o a.o gcc -c -g -Wall -I./ b.c -o b.o gcc -c -g -Wall -I./ c.c -o c.o gcc -c -g -Wall -I./ d.c -o d.o gcc main.o a.o b.o c.o d.o -o app
版本三
引入函数
引用函数也需要$
wildcard :指本目录中的所有文件,`wildcard *.c`就是本目录所有的.c文件 patsubst :查找替换函数 例:`patsubst %.c,%.o, $(wildcard *c)`,把所有在(wildcard *c)出现的.c替换成.o,这是`%.c,%.o`替换. .PHONY :生成伪目标,会在版本四中用到
通过引入函数,在改变一下Makefile的内容
CFLAGC= -c -g -Wall LDFLAGC= CPPFLAGS= -I./ src = $(wildcard *c) obj = $(patsubst %.c,%.o, $(src)) app:$(obj) gcc $^ -o $@ %.o:%.c gcc $(CFLAGC) $(CPPFLAGS) $< -o $@
执行过程:
$ make gcc -c -g -Wall -I./ a.c -o a.o gcc -c -g -Wall -I./ b.c -o b.o gcc -c -g -Wall -I./ c.c -o c.o gcc -c -g -Wall -I./ d.c -o d.o gcc -c -g -Wall -I./ main.c -o main.o gcc a.o b.o c.o d.o main.o -o app
执行结果没有问题
版本四
基本的Makefile的功能已经差不多了,但是每次运行make的时候都会生成.o文件和app可执行文件,在下次重新修改代码之后,还有手动删除.o文件和app可执行文件,之后再进行make操作,很繁琐,所以要进行下一步优化。初步完善后
CFLAGC= -c -g -Wall LDFLAGC= CPPFLAGS= -I./ src = $(wildcard *c) obj = $(patsubst %.c,%.o, $(src)) target = app $(target):$(obj) gcc $^ -o $@ %.o:%.c gcc $(CFLAGC) $(CPPFLAGS) $< -o $@ clean: rm -f $(obj) rm -f $(target)
当需要删除.o文件和app可执行文件的时候,可以执行
make clean命令,
$(obj)代表所有的.o文件,
$(target)代表app可执行文件。加
rm -f的目的是强制删除,这是为了避免在没有要删除文件的时候执行
make clean也就是
rm的时候会出现报错的情况。
但是有一种情况,当目录下有个文件名叫做clean,这个时候执行
make clean就不会执行删除命令了,会有下面这样的提示,
$ make clean make: “clean”是最新的。
为了避免这中情况,需要加入一个clean的目标
.PHONY:clean,这样make在执行
.PHONY这个目标的时候就会找依赖
clean,然后就会运行
clean里面的命令。
版本五
为了让这个Makefile在其他平台能够正常运行,尤其是在ARM处理器等其他处理器,要重新编译,就需要用到其他编译器,所以把gcc提取出来做成一个变量,这样下次换平台的时候直接改变量就行了,不用再把所有的gcc挨着改了CC : gcc,还有在命令前面加
-号,作用就是如果本条命令执行失败,不会停止执行下一条命令。
现阶段的使用的Makefile
CFLAGC= -c -g -Wall LDFLAGC= CPPFLAGS= -I./ CC = gcc src = $(wildcard *c) obj = $(patsubst %.c,%.o, $(src)) target = app $(target):$(obj) $(CC) $^ -o $@ %.o:%.c $(CC) $(CFLAGC) $(CPPFLAGS) $< -o $@ .PHONY:clean clean: -rm -f $(obj) -rm -f $(target)
注意:用这个Makefile的时候,文件夹里不要有其他项目的.c文件。
相关文章推荐
- python reshape()函数ValueError: total size of new array must be unchanged
- 3Sum
- pat 1037. Magic Coupon (25)
- cf478B-Random Teams 【排列组合】
- 移动端尺寸基础知识
- EnvironmentError:mysql config not found
- 十、solr中ik分词器加入同义词配置
- python学习笔记--随时更新
- ECMAScript 6新特性介绍
- 为什么win7 64位的没有debug?cmd中找不到
- Windows8.1优化,解决磁盘100%的问题
- 公历转农历算法
- 今天“农村打工仔”带你们走入Android的世界
- SVN-previous operation has not finished run 'cleanup' if it was interrupted
- 工作经验之OnClick的小细节
- 工作经验之OnClick的小细节
- TextView 使用自定义的字体和亮点
- mysqldump命令详解
- servlet
- Unity3D中的屏幕着色器和图像特效