背景

如果做过工程,或者读过一些优秀的开源代码的话;了解.c文件需要分开写,每个.c文件实现特定的一小部分功能,另外还有一些.h文件,这种文件主要引用一些头文件,声明一些函数(虽然函数可以直接定义无需声明,但是先声明再定义是一个好习惯,另外一些虚函数是仅仅声明而不定义的)与宏;这些.c文件再被不同的目录组织;以上就是工程一般的框架,这些.c文件既可能依赖.h文件,也可能依赖其他.c文件,单单一行gcc的编译命令已经解决不了,这时需要Makefile来指导编译过程!

语法规则

目标文件:依赖文件
|tab|编译规则

注:|tab|代表一个tab键

Demo

我的文件组织如下:

1
2
3
4
5
6
7
8
9
10
.
├── include
│ └── head.h
├── Makefile
└── src
├── add.c
├── div.c
├── master.c
├── mul.c
└── sub.c

head.h的代码如下:
1
2
3
4
5
6
7
8
9
#include <stdio.h>

int add(int a,int b);

int sub(int a,int b);

long mul(long a,long b);

float div(float a,float b);

add.c的代码如下:
1
2
3
4
5
6
#include "head.h"

int add(int a,int b)
{
return a+b;
}

差不多这个意思,其他的代码就自己完善吧;

最后master.c代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "head.h"

int main()
{
int a,b;
a=12;
b=3;
printf("%d add %d = %d\n",a,b,add(a,b));
printf("%d sub %d = %d\n",a,b,sub(a,b));
long ma,mb;
ma=12;
mb=3;
printf("%ld mul %ld = %ld\n",ma,mb,mul(ma,mb));
float fa,fb;
fa=12;
fb=3;
printf("%f div %f = %f\n",fa,fb,div(fa,fb));
return 0;
}

下面是Makefile文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
master:rely1.o rely2.o rely3.o rely4.o rely5.o
gcc -o master src/add.o src/sub.o src/mul.o src/div.o src/master.o
rely1.o: src/master.c include/head.h
gcc -c -I include src/master.c -o src/master.o
rely2.o: src/add.c include/head.h
gcc -c -I include src/add.c -o src/add.o
rely3.o: src/sub.c include/head.h
gcc -c -I include src/sub.c -o src/sub.o
rely4.o: src/mul.c include/head.h
gcc -c -I include src/mul.c -o src/mul.o
rely5.o: src/div.c include/head.h
gcc -c -I include src/div.c -o src/div.o
.PHONY:clean
clean:
find . -name '*.o' | xargs rm -f

下面make生成可执行文件:
1
2
3
4
5
6
7
8
$ make && make clean
gcc -c -I include src/master.c -o src/master.o
gcc -c -I include src/add.c -o src/add.o
gcc -c -I include src/sub.c -o src/sub.o
gcc -c -I include src/mul.c -o src/mul.o
gcc -c -I include src/div.c -o src/div.o
gcc -o master src/add.o src/sub.o src/mul.o src/div.o src/master.o
find . -name '*.o' | xargs rm -f

make clean会执行Makefile文件中clean下的命令,它会清除所有的目标文件(.o文件),因为已经不需要了!

我们测试一下可执行文件是否正确执行:

1
2
3
4
5
$ ./master
12 add 3 = 15
12 sub 3 = 9
12 mul 3 = 36
12.000000 div 3.000000 = 4.000000

注:可以看到Makefile中的rely1.o等等只是代号,真正目标文件的名称设定由编译规则指定。