原文: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