gcc有参数可以把源文件的依赖关系全部导出来,比如: -bash:~$gcc -MM main.c 输出:main.o: main.c main.h 使用 -MM参数是只导出自定义头文件,-M则会把系统头文件也导出来。以下是一个自动生成头文件依赖的Makefile:
- 1 PYINC = /usr/local/include/python2.5/
- 2 PYLIB = /usr/local/lib/python2.5/config
- 3 CFLAGS = -I$(PYINC) -I$(PYINC)/Include
- 4 LDFLAGS = -g -ggdb
- 5 LIBS = -lc -lm -lutil -export-dynamic -L$(PYLIB) -lpython2.5 -lpthread
- 6 CC = gcc
- 7 OBJS = main.o comm.o gamesys.o pyenter.o pyobject.o active.o protocol.o scene.o objmanage.o hash.o map.o placeobj.o pack.o livingobj.o
- 8 SRCS = ${OBJS:%.o=%.c}
- 9
- 10 all: depend driver
- 11
- 12 depend:
- 13 @$(CC) $(CFLAGS) -MM $(SRCS) > .depend
- 14
- 15 -include .depend
- 16
- 17 driver: $(OBJS)
- 18 $(CC) $(LDFLAGS) $(OBJS) -o driver $(LIBS)
- 19
- 20 install:
- 21 cp driver ./world/
- 22 clean:
- 23 rm -f $(OBJS)
- 24 rm -f driver
- 25 rm -f .depend
- 26
- 27 tags:
- 28 ctags *c *h
SRCS = ${OBJS:%.o=%.c}这句是把OBJS中所有的.o替换成.c 组成数组赋给SRCS,相当于:
SRCS = main.c comm.c gamesys.c pyenter.c pyobject.c active.c protocol.c scene.c objmanage.c hash.c map.c placeobj.c pack.c livingobj.c
@$(CC) $(CFLAGS) -MM $(SRCS) > .depend 这句生成依赖关系,并重定向到.depend中,后面把.depend文件include进来就可以使用了。
上面的Makefile在gmake下测试通过,没有指定.o文件的编译命令是利用的gmake隐含规则编译。
二 sample
main.o: main.c -----这里main.o只依赖main.c文件,不依赖main.c包含的头文件(即mian .c中包含的头文件更新的话,main.o也不更新)
gcc -c main.c
gcc -MM main.c的输出则是:
main.o: main.c defs.h -----依赖文件也就是main.c 和 defs.h 这两个文件,这两个文件中的任何一个更新了,那么目标main.o就要重新生成
所以可以将gcc -MM main.c的输出结果重新定向到 depend中,然后在 include .depend 。这样就相当于include了语句main.o: main.c defs.h ,即依赖main.c 和 defs.h头文件了。
注意,这里的gcc -MM main.c是执行时才会输出main.o: main.c defs.h
Tip:
通过编译器的参数MM或是M来获取目标文件的依赖文件按,即cpp和h头文件,只是为了实现cpp或是h头文件任何一个更新了就会触发更新目标文件。
而对于编译器编译cpp文件的shell命令中,是不需要带头文件的,编译器编译cpp文件时会去读cpp文件中include的头文件,然后在指定包含头文件的目录下去查找该头文件。
三 自写完整makefile小例
EXECUTE = sample
OBJS = sample.o
LIBS_PATH = -L ../../../lib --------------- -L makefile参数,指定依赖库所在目录,LIBS_PATH为自定义变量
LIBS = -ldependcies
INCLUDE = -I ../../ \ ----------------- -I makefile参数,执行包含的头文件所在目录
-I ../../../include
all: $(EXECUTE)
$(EXECUTE):$(OBJS)
gcc -o $(EXECUTE) $(OBJS) $(LIBS) $(LIBS_PATH)
sample.o:main.c ------------这里的唯一不足就是main.c所包含的头文件没有作为sample.o 的依赖文件列出来,可以参照二中的方式用MM参数方式列出头文件依赖
gcc $(INCLUDE) -c main.c ----------只有依赖文件main.c更新时,sample.o才会更新,才会执行此行shell命令
clean:
rm *.o $(EXECUTE)