让我们从一个例子来大概介绍make工具:
有个加密工具:
encrypt.h
void encrypt(char *message);
encrypt.c
#include "encrypt.h"
void encrypt(char *message){
while(*message){
*message = *message ^ 31;
message++;
}
}
主程序test.c
#include <stdio.h>
#include "encrypt.h"
int main(){
char c[] = "hello world";
encrypt(c);
printf("the result of encryption: %s\n",c);
return 0;
}
下面比较三种创建构建程序的方法:
一.用gcc一步到位的编译成一个可执行文件:
$ gcc encrypt.c test.c -o test
$ ./test
the result of encryption: wzssp?hpms{
二.或者先编译出目标文件(.o文件),再用这些目标文件创建程序:
~$ gcc -c encrypt.c
~$ gcc -c test.c
~$ ls
encrypt.c encrypt.h encrypt.o makefile test.c test.o
~$ gcc *.o -o ha
~$ ./ha
the result of encryption: wzssp?hpms{
三.用make工具构建:
1.创建名为makefile的文件:
encrypt.o:encrypt.h encrypt.c
gcc -c encrypt.c
test.o:test.c encrypt.h
gcc -c test.c
test:test.o encrypt.o
gcc test.o encrypt.o -o test
2.用make工具通过makefile构建程序:
~$ make test
gcc -c test.c
gcc test.o encrypt.o -o test
~$ ls
encrypt.c encrypt.h encrypt.o makefile test test.c test.o
~$ ./test
the result of encryption: wzssp?hpms{
如果程序很大,那么在遇到需要修改时,如何做会比较好呢,一种做法是先把所有的源文件生成目标文件(.o文件),放在某个文件夹下保存起来,然后记下要修改的文件,就可以用很快用gcc重新生成目标文件,再连接所有目标文件生成程序,
那么怎么知道哪个.o文件需要重新编译呢?一个很简单的方法就是比较.o文件与.c文件的时间戳就可以知道了。如果.c文件比.o文件要新,就要重新编译。
这么简单的规则,有没有办法自动化呢?有,就是用make工具。make是一个可以替你运行编译命令的工具。make会检查源文件和目标文件的时间戳,如果目标文件过期,make就会重新编译它。但是要做到这些事情,需要告诉make源代码的一些情况。那就是make需要知道文件之间的依赖关系,同时还需要告诉make你具体想如何构建代码。
那么make它想知道什么呢?首先make编译的文件叫目标。对每个目标,make需要知道两件事:
- 依赖项:生成目标需要用哪些文件
- 生成方法:生成该文件时要用哪些指令
依赖项和生成方法合在一起构成了一条规则,有了规则,make就知道如何生成目标。
从上面makefile文件,拿一条规则出来讲吧,如:
encrypt.o:encrypt.h encrypt.c
gcc -c encrypt.c
encrypt.o就叫目标,因为我们想要生成这个文件。encrypt.h ,encrypt.c是依赖项,因为编译器在创建encrypt.o时,需要它们。
而生成方法就是将encrypt.h, encrypt.c转化为encrypt.o的编译指令:
gcc -c encrypt.c
所有的依赖项和生成方法的细节需要保存在一个名为makefile或Makefile的文件里。
只要告诉了make依赖项及生成方法,就可以让make决定什么时候重新编译目标文件了。
make是最早出现用来从源代码自动构建程序的工具。一旦有很多文件,手动编译、链接它们真是个恶梦,使用make不但减轻了编译文件时的痛苦,还节约了不少时间,管理也方便多了。另个提醒一点,makefile会调用底层操作系统的命令,所以有时不能在其他操作系统中使用。处理makefile的格式时要小心,别忘了用tab来缩进,不是空格。