第十篇 变量与函数的综合实战
在实际的工程项目中,生成的目标文件、最终可执行文件以及其它中间文件都需要进行管理,而不是生成在同一个目录下,本次,我们给出下面的实战需求:
1、自动生成target文件夹存放可执行文件。
2、自动生成objs文件夹存放编译生成的目标文件(*.o)。
3、支持调试版本的编译选项。
4、考虑代码的扩展性。
下面先引入一些需要用到的工具原料,如下:
wildcard和addprefix都是make中的预定义函数,wildcard用来获取当前工作目录中的符合_pattern的文件并返回一个文件列表或者目录列表。
addprefix用于给名字列表_names中的每一个名字增加前缀。
关键技巧:
规则中的模式替换:
上图中的模式替换写法为%.o : %.c,这种写法同第六篇中的模式规则有所不同,所代表的意义也不同,第六篇中的写法为OBJS := func.o main.o,OBJS : %.o : %c,意义为把OBJS列表中符合%.o模式的目标名给取出来,然后在将取出来的目标名后缀换位.c作为依赖。因此,第六篇中这种模式替换写法针对的是列表。
本篇的写法中,直接对当前工作目录下的文件进行模式匹配,即%.c用于模式匹配当前目录下的文件,例如,当前目录下有func.c和main.c文件,make匹配到func.c,%.o用于将%.c匹配成功的文件名进行模式替换,.c替换为.o,从而生成func.o : func.c这个规则,而main.c同理。本篇中的模式替换针对的目标是当前工作目录。
综合的示例的编译依赖如下:
下面给出makefile程序:
1 CC := gcc 2 MKDIR := mkdir 3 RM := rm -fr 4 5 DIR_OBJS := objs 6 DIR_TARGET := target 7 8 DIRS := $(DIR_OBJS) $(DIR_TARGET) 9 10 TARGET := $(DIR_TARGET)/hello-makefile.out 11 # main.c const.c func.c 12 SRCS := $(wildcard *.c) 13 # main.o const.o func.o 14 OBJS := $(SRCS:.c=.o) 15 # objs/main.o objs/const.o objs/func.o 16 OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS)) 17 18 .PHONY : rebuild clean all 19 20 $(TARGET) : $(DIRS) $(OBJS) 21 $(CC) -o $@ $(OBJS) 22 @echo "Target File ==> $@" 23 24 $(DIRS) : 25 $(MKDIR) $@ 26 27 28 $(DIR_OBJS)/%.o : %.c 29 ifeq ($(DEBUG),true) 30 $(CC) -o $@ -g -c $^ 31 else 32 $(CC) -o $@ -c $^ 33 endif 34 35 rebuild : clean all 36 37 all : $(TARGET) 38 39 clean : 40 $(RM) $(DIRS) 41 42
第28行的模式规则$(DIR_OBJS)/%.o : %.c中,加上了路径前缀,但是不影响模式匹配的含义,依旧根据%.o : %.c模式规则在当前目录下搜索文件,然后将.c替换为.o,并且添加目录前缀作为整体目标,也即将目标生成到指定的目录下。
小结:
1、目录可以成为目标的依赖,在规则中创建目录。
2、预定义函数是makefile实战时不可或缺的部分。
3、规则中的模式匹配可以直接针对目录中的文件。
4、可以使用命令行变量编译特殊的目标版本。