makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目
录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,
甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
举个简单的例子吧:主程序(main.c)、函数代码(getop.c, stack.c, getch.c)、头文件(calc.h)。
一般的,我们会使用:gcc -o calc main.c getch.c getop.c stack.c -I.
来编译。-I.是指gcc在当前目录(.)下寻找include文件。如果不用makefile,在测试-修改-调试过程中,如果我们不想重
敲那条 编译指令的话,我们必须不停地在终端中按上下键来寻找最后的那条编译指令。不幸的是,这种编译方法有两
个缺陷:1. 当你把编译指令丢失或者换电脑的时候,这样效率会很低;2. 当我们只修改了一个.c文件时,每一次都将
必须重新编译所有的文件,这非常耗时,不划算。所以最简单的makefile写法如下:
第一行:calc: main.c getch.c getop.c stack.c
第二行: gcc -o calc main.c getch.c getop.c stack.c -I.
如果把这些语句写入一个叫Makefile或者makefile的文件,然后在终端中输入make,她将会按你在makefile中要求地
编译。注 意:第一行中并没有任何参数,只是在冒号(:)后列出编译中所需的文件,当第一行中的任何文件中更改时,
make就知道calc需要重新编译了。现在我们 已经解决了问题1,不用上下按箭头了,但是对于问题2依旧没有很好地
解决。注意,非常重要:gcc前面必须有一个tab,在任何指令之前都要有一个 tab,不然make就会罢工的。下面就让事情变得更有效率一点:
第一行:CC = gcc
第二行:CFLAGS = -I.
第三行:calc: main.c getch.c getop.c stack.c
第四行:$(CC) -o calc main.c getch.c getop.c stack.c $(CFLAGS)
现在我们新定义了两个常量CC和CFLAGS。这些是与make交流的特殊的常量,让make知道我们要怎么编译.c文件,
CC是C编译器所使用的,CFLAGS是编译用的参数。make会先分别编译.c文件,然后生成可执行文件calc。
这种形式的makefile在小项目中非常有效,但是有一个遗憾:include文件的变动。如果我们修改了calc.h文件,make
是不会重新 编译.c文件的,事实上我们需要重新编译。为了解决这一问题,我们必须告诉make所有的.c文件依赖于.h
文件。我们可以在makefile中增加一条 规则:
第一行:CC = gcc
第二行:CFLAGS = -I.
第三行:DEPS = calc.h
第四行:%.o: %.c $(DEPS)
第五行: $(CC) -c -o $@ $< $(CFLAGS)
第六行:calc: main.o getch.o getop.o stack.o
第七行: $(CC) -o calc main.o getch.o getop.o stack.o $(CFLAGS)
首先宏定义DEPS,声明.c文件所依赖的.h文件。然后我们定义一条规则,为所有的.c文件生成一个.o文件。规则描
述:.o文件依赖于.c文件 和DEPS中声明的.h文件,为了产生.o文件,make需要使用CC中声明的编译器来编译.c文
件。-c 意味着产生object文件,-o $@ 意思是编译生成的文件用上面的%.o来命名,$< 指依赖关系中的第一项
(%.c)CFLAGS的定义和之前一样。