使用keil、mdk、avr等工具开发时,点点鼠标就可以编译了,但是你是否理解它的内部机制呢?它是怎么组织管理程序的?怎么决定编译哪一个文件的?这些其实都是和Makefile息息相关
说起作用的话,得看看我们平时怎么使用GCC进行编译,比如我们需要编译main.c和sub.c生成可执行程序test, 那么我们有两种方式进行编译:
方式一用于源文件比较少的程序,方式二用于源文件比较多的程序。但是如果源文件很多时,我们一条一条输入命令就变得很不高效。这时我们的Makefile就起作用了。
Makefile可以根据文件的更新时间选择性的进行执行相应的命令。
Makefile的书写框架如下:
目标1:依赖1 依赖2 ...
【TAB】命令1
目标2:依赖3 依赖4 ...
【TAB】命令2
......
Makefile的执行情况如下:
源程序如下:
main.c
#include <stdio.h>
#include "sub.h"
int main(int argc, char *argv[])
{
int i;
printf("Main fun!\n");
sub_fun();
return 0;
}
sub.c
void sub_fun(void)
{
printf("Sub fun!\n");
}
Makefile文件我们一般是按照命令的执行顺序进行编写,首先第一行是最后执行的命令,如:
gcc -o test main.o sub.o 可见目标文件为test 依赖为 main.o sub.o
则第一部分如下:
test : main.o sub.o
gcc -o test main.o sub.o
随后部分就是依次生成目标文件
生成main.o如下:
main.o : main.c
gcc -c -o main.o main.c
生成sub.o如下:
sub.o : sub.c
gcc -c -o sub.o sub.c
合并之后的Makefile:
test : main.o sub.o
gcc -o test main.o sub.o
main.o : main.c
gcc -c -o main.o main.c
sub.o : sub.c
gcc -c -o sub.o sub.c
Makefile执行过程为,先判断test是否存在,不存在则想执行命令, 发现main.o和sub.o也不存在,,那么会往下查找这两个文件,发现main.o 依赖main.c 那么执行gcc -c -o main.o main.c, 发现sub.o 依赖sub.c 执行gcc -c -o sub.o sub.c, 再返回执行gcc -o test main.o sub.o
如下图为执行的顺序图
接着我们试图修改main.c,再次编译:
编译过程为判断main.o和sub.o有没有更新,发现main.o依赖main.c, main,c有更新,那么需要执行gcc -c -o main.o main.c, 发现sub.o依赖sub.c, 而sub.c没有更新,那么不执行,再发现main.o有更新了, 那么需要执行gcc -o test main.o sub.o 。
为了再次验证makefile是不是根据时间来更新的,我们这里使用ls -l查看文件的时间,和使用touch来更新文件时间,重新编译:
和我们想的一样