make--变量与函数的综合示例 自动生成依赖关系
一.变量与函数的示例
示例的要求 SRC : = $(wildcard *.c) 2.根据源文件列表生成目标目标文件列表(变量的值替换) OBJS := $(SRCS:.c=.o) 3.对每一个目标文件列表加上路径前缀(函数调用) OBJS := $(addprefix path/,$(OBJS)) 规则中的模式替换(目录结构) 编译规则的依赖 编译的示例代码及运行结果 CC := gcc MKDIR := mkdir RM := rm -fr DIR_OBJS := objs DIR_TARGET := target DIRS := $(DIR_OBJS) $(DIR_TARGET) TARGET := $(DIR_TARGET)/hello-makefile.out # main.c const.c func.c SRCS := $(wildcard *.c) # main.o const.o func.o OBJS := $(SRCS:.c=.o) # objs/main.o objs/const.o objs/func.o OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS)) .PHONY : rebuild clean all $(TARGET) : $(DIRS) $(OBJS) $(CC) -o [email?protected] $(OBJS) @echo "Target File ==> [email?protected]" $(DIRS) : $(MKDIR) [email?protected] $(DIR_OBJS)/%.o : %.c ifeq ($(DEBUG),true) $(CC) -o [email?protected] -g -c $^ else $(CC) -o [email?protected] -c $^ endif rebuild : clean all all : $(TARGET) clean : $(RM) $(DIRS) 运行结果 小结: 1.目录可以成为目标的依赖,在规则中创建目录 2.预定义函数是makefile不可或缺的部分 3.规则这的模式匹配可以直接针对目录中的文件 4.可以使用命令行变量编译特殊的目标版本 二.自动生成依赖关系一.编译行为带来的缺陷 在第一张图可以看出main.c与func.c是依赖于func.h的,此时将func.h中的打印信息改了之后运行的结果如下图所示 由运行的结果可以看到把打印的信息改变了,但是make之后的结果并没有改变,这是因为并没有把func.h算子啊依赖上去,所以在它的打印信息改变之后,结果还是一样的 ,需要进行以下修改才能实现修改打印信息,运行结果也改变(如图所示) 由上面的解决方法可以得出 1.头文件作为依赖条出现于每个目标对应的规则中 2.当头文件改动,任何源文件都将被重新编译 3.当项目中头文件数量巨大时,makefile将很难维护 二.改进的方法 B.sed的正则表达式支持 1.在sed中可以用正在表达式匹配替换目标 2.并且可以使用匹配的目标生成替换结果 C.gcc关键编译选项(生成依赖关系) 1.获取目标的完整依赖关系(gcc -M test.c) 2.获取目标的部分依赖关系(gcc -MM test.c) D.makefile中的include关键字 1.类似C语言中的include 2.将其它文件的内容原封不动的搬入当前文件 make对include关键字的处理方式 a.在当前目录搜索或指定目录搜索目标文件 1.搜索成功:将文件搬入当前makefile中 2.搜索失败:产生警告 a.以文件名作为目标查找并执行对应规则 b.当前文件名对应的规则不存在时,最终产生错误 代码示例及运行结果 makefile中命令的执行机制 1.规则中的每个命令默认是在一个新的进程中执行 2.可以通过连续符(;)将多个命令组成一个命令 3.组合的命令依次在同一个进程中被执行 4.set -e指定发生错误后立即退出执行 示例: 该代码主要的目的是想在当前文件夹下新建test文件夹,然后进入test文件夹,创建subtest文件夹,但是make之后的结果如图所示,可以看到subtest与test文件夹在同一级目录,不是我们要的结果 经过修改之后的代码及运行结果 三.综合示例思路:通过gcc -MM 和sed得到.dep依赖文件,通过inclue指令包含所有的.dep依赖文件 运行的结果: 该示例可能会出现的问题是如何在makefile在组织.dep文件到指定目录 解决的思路: 当include发现.dep文件不存在: 1.通过规则和命令创建deps文件 2.将所有.dep文件创建到deps文件夹 3..dep文件记录目标文件的依赖关系 代码实现 总结:a.使用减号(-)不但关闭了include发出的警告,同时关闭了错误,当错误发生时make将忽略这些错误b.当目标文件不存在(以文件名查找规则,并执行)c.当目标文件不存在,且查找到的规则在创建了目标文件(将创建成功的目标文件包含进当前makefile)d.当目标文件存在(将目标文件包含进当前makefile,以目标文件名查找是否有相应的规则)e.当目标文件存在,且目标名对应的规则被执行(规则中的命令更新了目标文件,make重新包含目标文件,替换之前包含的内容),目标文件未被更新(无操作) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |