1. 需求分析
(1)工程项目中不希望源码文件夹在编译时被改动(只读文件夹)
(2)在编译时自动创建文件夹(build)用于存放编译结果
(3)编译过程中能够自动搜索需要的文件
(4)makefile 易于扩展,能够复用于相同类型的项目
(5)支持调试版本的编译选项
2. 项目类型分析
3. 工具原料
(1)wildcard 函数
函数用法:
函数功能:获取 $(DIR) 文件夹中满足 _pattern 的文件
(2)notdir 函数
函数用法:
函数功能:去除 _names 中每一个文件名的路径前缀
(3)patsubst 函数
函数用法:
函数功能:将 _text 中符合 _pattern 的部分替换为 replacement
4. 关键技巧
(1)自动获取源文件列表(函数调用)
(2)根据源文件列表生成目标文件列表(变量的值替换)
(3)替换每一个目标文件的路径前缀(函数调用)
5. 编译规则的依赖
值得斟酌的问题?
对于规模较小的项目,makefile 中是否也需要使用自动生成依赖关系的解决方案呢?
编程实验:
.PHONY : all clean DIR_BUILD := build DIR_SRC := src DIR_INC := inc TYPE_INC := .h TYPE_SRC := .c TYPE_OBJ := .o CC := gcc LFLAGS := CFLAGS := -I $(DIR_INC) ifeq ($(DEBUG),true) CFLAGS += -g endif MKDIR := mkdir RM := rm -fr APP := $(DIR_BUILD)/app.out HDRS := $(wildcard $(DIR_INC)/*$(TYPE_INC)) HDRS := $(notdir $(HDRS)) OBJS := $(wildcard $(DIR_SRC)/*$(TYPE_SRC)) OBJS := $(OBJS:$(TYPE_SRC)=$(TYPE_OBJ)) OBJS := $(patsubst $(DIR_SRC)/%, $(DIR_BUILD)/%, $(OBJS)) vpath %$(TYPE_INC) $(DIR_INC) vpath %$(TYPE_SRC) $(DIR_SRC) all : $(DIR_BUILD) $(APP) @echo "Target File ==> $(APP)" $(DIR_BUILD) : $(MKDIR) $@ $(APP) : $(OBJS) $(CC) $(LFLAGS) -o $@ $^ $(DIR_BUILD)/%$(TYPE_OBJ) : %$(TYPE_SRC) $(HDRS) $(CC) $(CFLAGS) -o $@ -c $< clean : $(RM) $(DIR_BUILD)
运行结果:
6. 小结
(1)工程项目中不希望源码文件夹在编译时被改动(只读文件夹)
(2)模式规则的灵活运用使得makefile具有复用性
(3)变量的灵活运用使得makefile具有扩展性
(4)规模较小的项目没必要使用自动生成依赖关系的解决方案
(5)规模较小的项目可以直接让源文件依赖于头文件(易于维护)