makefile
makefile抽象层面的理解
学习某一样东西之前一定要明确学习的目的,即学习了这项工具能解决一些什么问题,其优势是什么?
makefile的优势就是能够动态根据文件的新旧来决定是否编译对应的文件,倘若每次编译一个项目都重新编译,特别是大项目的时候,岂不是很浪费时间?makefile能自动根据依赖关系解决这个问题,对于已经编译过的文件不再重新编译,而只选择编译尚未编译(或者新)的文件。
那么如何实现自动编译新文件呢?makefile是如何识别哪些是新的文件哪些是旧的文件的呢?
这就是makefile的核心--依赖关系
makefile中的语句就是为描述各种依赖关系而建立的。
例如下面这个例子
main:arithmetic.o main.o myprint.o
main.o:main.c
gcc -c main.c -o main.o
arithmetic.o:arithmetic.c
gcc -c arithmetic.c -o arithmetic.o
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
翻译过来,用通俗的话说就是:
- 如果main的修改时间在arithmetic.o main.o myprint.o的修改时间之前,那么就更新arithmetic.o main.o myprint.o (实际上就是确保main是最新的,如果不是,就更新冒号右边的文件。下面的语句也是类似的)
- 保证main.o是最新的
- 保证arithmetic.o是最新的
- 保证myprint.o是最新的
那么如何更新这个文件呢?就通过冒号:
下面一行的语句(有时可省略)来进行更新的操作(gcc编译出新文件覆盖掉旧文件)
显然,如果每一个源程序都需要一一给出依赖关系那么这个工作量无疑是巨大的。为此makefile提供了一些更简便的操作方法来管理,如提供变量,嵌入shell语句等。这些操作方法使得makefile管理文件变得简单的同时,也使得makefile的学习成本增加。但是只要理解了上面makefile的基本原理,那么makefile中的其他高级操作不过是对这种建立依赖关系的方法进行了扩充,只要多背几条语句/语法规则即可。
makefile简单例子
下面,通过一个具体的实例来说明更新的过程。
main.c
#include <stdio.h>
#include "arithmetic.h"
#include "myprint.h"
int main()
{
int a=1;
int b=1;
printf("a+b=%d\n",add(a,b));
myprint();
printf("hello world!\n");
return 0;
}
myprint.h
#ifndef __MYPRINT
#define __MYPRINT
#include <stdio.h>
void myprint(void);
#endif
myprint.c
#include "myprint.h"
void myprint(void)
{
printf("my print\n");
}
arithmetic.h
#ifndef __ARITHMETIC
#define __ARITHMETIC
int add(int a ,int b);
#endif
arithmetic.c
#include "arithmetic.h"
int add(int a ,int b)
{
return a+b;
}
makefile
版本1
main:arithmetic.o main.o myprint.o
main.o:main.c
gcc -c main.c -o main.o
arithmetic.o:arithmetic.c
gcc -c arithmetic.c -o arithmetic.o
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
.PHONY:clean
clean:
rm -rf *.o
版本2
main:arithmetic.o main.o myprint.o
main.o:main.c
gcc -c $^ -o $@
arithmetic.o:arithmetic.c
gcc -c $^ -o $@
myprint.o:myprint.c
gcc -c $^ -o $@
.PHONY:clean
clean:
rm -rf *.o
版本3
main:arithmetic.o main.o myprint.o
%.o:%.c
gcc -c $^ -o $@
.PHONY:clean
clean:
rm -rf *.o
版本4
OBJS = main.o\
myprint.o\
arithmetic.o
main:$(OBJS)
%.o:%.c
gcc -c $^ -o $@
.PHONY:clean
clean:
rm -rf *.o
一般能理解并能手动写出版本4的makefile就足够用了。上面例程是仿照下面的博客做的,并加入了自己的一些理解和修改,感谢下面博客博主的热心分享。
具体的语法这里也不再给出具体说明,因为这些资源网络上各处都有。更重要的是对makefile思想以及抽象层面上的理解。