?
原文:http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
?
?
Hellomake.c
?
?
int main() {
// call a function in another file
myPrintHelloMake();
?
return(0);
}
?
?
hellofunc.c
?
#include <stdio.h>
void myPrintHelloMake(void) {
?
printf("Hello makefiles!\n");
?
return;
}
?
hellomake.h
?
/*
example include file
*/
?
void myPrintHelloMake(void);
?
?
?
通常我们会像这样来编译:
gcc -o hellomake hellomake.c hellofunc.c -I.
它将2个c文件编译成可执行文件hellomake. -I.表示当初目录被gcc包含,因为我们需要用到当前目录下面的hellomake.h文件
没有makefile文件的话,你能通过箭头的上下来找到你刚才编译的这条命令,而不用你每次都敲下它.
这样的编译方式有两个缺点,如果你切换窗口,那么就需要重新敲上面的命令了.并且这种编译方式你每次都需要编译所有的文件,
这样是低效和耗时的.所以我们需要有个makefile文件.
?
?
最简单的makefile文件是这样的
makefile1
?
hellomake:hellomake.c?hellofunc.c
????????gcc?-o?hellomake?hellomake.c?hellofunc.c?-I./
?
如果你把上面的规则放入makefile或Makefile文件中,然后敲下make命令,它就会自动编译文件了.注意gcc前面必须是一个tab键,但是这种方式
还是没有解决上面所说的耗时和低效的问题,它还是会编译每一个文件.
makefile2
?
CC=gcc
CFLAGS=-I.
?
hellomake:?hellomake.o?hellofunc.o
????????$(CC)?-o?hellomake?hellomake.o?hellofunc.o?-I.
?
我们现在定义了常量CC和CFLAGS,通过把hellomake.o?hellofunc.o放入依赖规则里面,make就知道需要先单独编译c文件,然后才能再生成可以执行文件.
使用这种方式对于小项目还是比较有效的.但是我们忽略了一个事情,头文件的依赖.如果我们对hellomake.h头文件进行了更改,使用这makefile的话,它
就不会重新编译c文件了.所以我们需要把头文件写到规则里面去.于是就有了makefile3
?
makefile3
?
?
CC=gcc
CFLAGS=-I.
DEPS?=?hellomake.h
?
%.o:?%.c?$(DEPS)
????????$(CC)?-c?-o?$@?$<?$(CFLAGS)
????????
hellomake2:?hellomake.o?hellofunc.o?
????????gcc?-o?hellomake?hellomake.o?hellofunc.o?-I.
我们添加了.h文件的一个变量DEPS,??%.o:?%.c?$(DEPS)????%?这个百分号是一个通配符?%.o表示所有的.o文件??这个规则表示所有的.o文件依赖于.c文件和DEPS中定义的.h
文件.?$@表示的冒号:左边的,即?%.o,??%<表示冒号:右边的第一个,即%.c?不包括接着的$(DEPS)
?
?
makefile4
?
C=gcc
CFLAGS=-I.
DEPS?=?hellomake.h
OBJ?=?hellomake.o?hellofunc.o?
?
%.o:?%.c?$(DEPS)
????????$(CC)?-c?-o?$@?$<?$(CFLAGS)
????????
hellomake:?$(OBJ)
????????gcc?-o?$@?$^?$(CFLAGS)
?
?
makefile5
如果我们想要把.h文件都放到include目录中,把.c文件都放到src目录中,还有一些本地的lib文件放到lib目录中,下面的这makefile文件定义了include文件和lib文件的目录,然后
把.o的目标文件放到obj目录当中,这个makefile文件应当放在src目录当中,?.PHONY规则保证了clean总是去执行?删除编译过程中的.o文件
?
?
IDIR?=../include
CC=gcc
CFLAGS=-I$(IDIR)
?
ODIR=obj
LDIR?=../lib
?
LIBS=-lm
?
_DEPS?=?hellomake.h
DEPS?=?$(patsubst?%,$(IDIR)/%,$(_DEPS))
?
_OBJ?=?hellomake.o?hellofunc.o?
OBJ?=?$(patsubst?%,$(ODIR)/%,$(_OBJ))
?
?
$(ODIR)/%.o:?%.c?$(DEPS)
????????$(CC)?-c?-o?$@?$<?$(CFLAGS)?
hellomake:?$(OBJ)
????????gcc?-o?$@?$^?$(CFLAGS)?$(LIBS)
.PHONY:?clean
?
clean:
rm?-f?$(ODIR)/*.0
?
?