Makefile的使用
- 什么是Makefile
- 目标和依赖
- GCC编译多个文件
- Makefile编译
- 伪目标
什么是Makefile
Makefile是编译工程的工具,包含以下两部分:
- make工具:可以找出项目里修改过的文件和受修改文件影响的其他文件进行单独编译,避免重复编译。
- Makefile文件:存放文件之间的依赖关系和编译规则
目标和依赖
新建一个文件夹test,进入文件夹内创建Makefile文件(sudo vi Makefile
),编辑以下内容:
targeta:targetc targetb
ls -lh
targetb:
touch test.txt
targetc:
pwd
targetd:
rm -f test.txt
- targeta:Makefile的第一个目标,并依赖于targetc和targetb,并且本身的命令为
ls -lh
,它是默认目标和最终目标(make命令发现的第一个目标) - targetb:第二个目标,无依赖,本身命令为
touch test.txt
- targetc:第三个目标,无依赖,本身命令为
pwd
- targetd:第四个目标,无依赖,也没目标依赖与它,本身命令为
rm -f test.txt
,所以直接make不会被调用
目标可以是代号,也可以是文件
依赖是要达成目标所需要的文件或其他目标
make
命令:在当前目录搜索Makefile或makefile文件并执行
由截图可知执行顺序为:先执行依赖,在执行目标;
也可以指定执行某个具体的目标例如make target
target可以是(targeta,targetb,targetc,targetd)。
GCC编译多个文件
工程目录下有三个文件
hello_main.c
#include "hello_func.h"
int main()
{
hello_func();
return 0;
}
hello_func.c
#include <stdio.h>
#include "hello_func.h"
void hello_func(void)
{
printf("hello, world! This is a C program.\n");
for (int i=0; i<10; i++ ) {
printf("output i=%d\n",i);
}
}
hello_func.h
void hello_func(void);
使用gcc编译:gcc -o hello_main hello_main.c hello_func.c -I .
-o:设置输出文件名为hello_main
源文件:hello_main.c hello_func.c
-I:头文件路径为"."当前目录
Makefile编译
将GCC的编译指令放入Makefile文件中
hello_main: hello_main.c hello_func.c
gcc -o hello_main hello_main.c hello_func.c -I .
#clean目标,用来删除编译生成的文件
clean:
rm -f *.o hello_main
默认目标hello_main和生成文件hello_main同名:此处的目标hello_main在Makefile看来已经是一个目标文件hello_main。
这样做的好处是每次make执行时会检查hello_main
和依赖文件hello_main.c hello_func.c
的日期,如果hello_main
的日期比依赖文件新,那么就不会执行,反之执行。
由图可以看出hello_main是最新的,所以不会被执行。如果我们用touch hello_func.c
更新下时间,make指令就会被执行。
伪目标
前面我们在Makefile中编写的目标,在make看来其实都是目标文件,例如make在执行的时候由于在目录找不到targeta文件,所以每次maketargeta的时候,它都会去执行targeta的命令,期待执行后能得到名为targeta的同名文件。如果目录下真的有targeta、targetb、targetc的文件,即假如目标文件和依赖文件都存在且是最新的,那么maketargeta就不会被正常执行了,这会引起误会。
为了避免这种情况,Makefile使用.PHONY
前缀来区分目标代号 (伪目标) 和目标文件,只要我们不期待生成目标文件,就应该定义成伪目标。
hello_main: hello_main.c hello_func.c
gcc -o hello_main hello_main.c hello_func.c -I .
#clean伪目标
.PHONY:clean
clean:
rm -f *.o hello_main
如果以上代码中不写“.PHONY:clean”语句,并且在目录下创建一个名为clean的文件,那么当 执行“make clean”时,clean的命令并不会被执行。