一、Makefile概述
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。Makefile的基本语法规则为:
目标: 依赖
操作
例如我们要把一个main.c
编译成app
,这里目标是app
,源是main.c
,编译的命令为gcc main.c -o app
。那么它的Makefile为:
app: main.c
gcc main.c -o app
一个要注意的地方是 Makefile
文件的名字只能是Makefile
,编写完成后在同级目录输入make
即可完成编译。这里创建两个文件main.c
和Makefile
:
> cat main.c
#include <stdio.h>
int main() {
printf("HelloWorld\n");
return 0;
}
> vi Makefile
> cat Makefile
app: main.c
gcc main.c -o app
编译:
> make
gcc main.c -o app # 执行编译
> ./app
HelloWorld
使用Makefile还有一个好处是不会重复编译:如果一个目标的依赖项在上次编译过后没有更改,那么在下次编译时会提示目标已是最新,该项编译自动跳过。这个功能对大型项目来说十分友好,因为可以减去很多重复编译的时间。
> make
make: ''app'' is up to date.
对于Makefile而言,它本身可能包含多个目标,默认情况是编译第一个不包含通配符的目标。此时如果需要编译其他目标需要手动指定,例如这里的目标是app
,输入make app
即可指定编译app
这个目标。
二、依赖项
Makefile在编译过程中会自动解决依赖关系,依赖项中没有生成的选项会自动根据规则生成:
app: main.c abc
gcc main.c -o app
abc:
echo "abc" > /dev/null
输入make
命令,会默认生成第一个目标app
,而app
依赖abc
所以会先生成abc
:
> make
echo "abc" > /dev/null
gcc main.c -o app
三、变量
3.1 内置变量
Makefile中定义了一些内置的变量:
$@
:表示目标$^
:表示所有的依赖$<
:第一个依赖项
合理运用内置变量能减少很大的工作量,例如上面的Makefile可改成:
app: main.c
gcc $< -o $@
3.2 自定义变量
四、函数
五、通配符
六、.PHONY
.PHONY
用来生成为伪目标,用于解决一种目标已经存在于目录的情形。
> ls # 目录下有两个文件
main.c Makefile
> cat main.c # 代码文件
#include <stdio.h>
int main() {
return 0;
}
> cat Makefile # Makefile文件
app: main.c
gcc main.c -o app
clean:
rm app
执行make
命令编译程序,make clean
删除目标程序:
> make # 编译
gcc main.c -o app
> ls
app main.c Makefile
> make clean # 清除
rm app
> ls
main.c Makefile
以上操作能正常完成,但是当目标文件夹下有一个clean文件时,操作就会失败:
> touch clean
> make
gcc main.c -o app
> make clean # 操作失败
make: ''clean'' is up to date.
> ls
app clean main.c Makefile
原因很简单,因为本地有一个clean,Makefile执行时检测到clean文件所以不会生成目标。
此时就需要.PHONY
关键字来生成为伪目标,修改Makefile中clean目标为以下内容即可:
.PHONY: clean
clean:
rm app -f
此处评论已关闭