makefile |
您所在的位置:网站首页 › makefile依赖文件不存在 › makefile |
自动生成依赖关系
1、编译行为带来的缺陷
预处理器将头文件中的代码直接插入源文件
编译器只通过预处理后的源文件产生目标文件
因此,规则中以源文件为依赖,命令可能无法执行
示例1 观察以下makefile文件是否正确:当修改func.h中宏HELLO的内容后,执行make命令发现,编译器无法更新main.c和func.c,进而无法更新执行的结果:原因在于func.h中更新的内容无法自动更新到func.c和main.c文件中,进而导致编译的hello.out文件结果无任何变化。 func.h #ifndef FUNC.H #define FUNC.H #define HELLO "hello makefile" void foo(); #endif func.c #include "stdio.h" #include "func.h" void foo() { printf("void foo():%s\n",HELLO); } main.c #include "stdio.h" #include "func.h" extern void foo(); int main() { foo(); return 0; } makefile OBJS := func.o main.o hello.out := $(OBJS) @gcc -o $@ $^ @echo "Target File => $@" $(OBJS) : %.o : %.c @gcc -o $@ -c $^![]() ![]() 头文件的更改会更新到相关的源文件中,并更新到最终的目标文件 缺点: 当头文件改动,任何源文件都将被重新编译(编译低效) 当项目中头文件数量巨大时,makefile将很难维护 解决方案2: 通过命令自动生成对头文件的依赖 将生成的依赖自动包含进makefile中 当头文件改动后,自动确认需要重新编译的文件 针对解决方案2需要使用的技术: (1) linux的sed命令 sed是一个流编辑器,用于流文本的修改(增/删/改/查) sed可用于流文本中的字符串替换 sed的字符串替换方式为:sed 's:src:des:g'![]() test的内容将变为xyz+xyz+xyz sed的正则表达式支持 在sed中可以用正则表达式匹配替换目标 并且可以使用匹配的目标生成替换结果 例如 sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'示例2--sed用法 ![]() ![]() 示例3-1--include用法--目标文件不存在,目标规则不存在--无操作,直接报错 .PHONY : all include test.txt all : @echo "this is $@"![]() ![]() --执行make命令,将执行makefile中的第一条规则 ![]() ![]() 示例3-5-1--include不使用(-)会报告所有的错误和警告 .PHONY : all include test.txt all : @echo "this is $@"![]() ![]() 示例3-6-1-include执行的规则中不存在依赖;则会将规则直接包含进makefile .PHONY : all -include test.txt all : @echo "this is $@" test.txt : @echo "creating $@ ..." @echo "other"![]() test.txt all : a.txt示例3-6-2 当规则文件比依赖文件内容要新--test.txt比b.txt时间戳更新,执行make all结果如下: ![]() 示例3-6-2 当依赖文件比规则文件内容要新--b.txt比test.txt时间戳更新,执行make all结果如下: ![]() ![]() ![]() 观察上述代码, 示例5 func.h #ifndef FUNC_H #define FUNC_H #define HELLO "hello world" void foo(); #endiffunc.c #include "stdio.h" #include "func.h" void foo() { printf("void foo():%s\n",HELLO); }main.c #include "stdio.h" #include "func.h" extern void foo(); int main() { foo(); return 0; }makefile .PHONY : all clean MKDIR := mkdir RM := rm -rf CC := gcc DIR_DEPS := deps SRCS := $(wildcard *.c) DEPS := $(SRCS:.c=.dep) DEPS := $(addprefix $(DIR_DEPS)/,$(DEPS)) ifeq ("$(MAKECMDGOALS)","all") -include $(DEPS) endif ifeq ("$(MAKECMDGOALS)","") -include $(DEPS) endif all : @echo "$@" $(DIR_DEPS) : $(MKDIR) $@ ifeq ("$(wildcard $(DIR_DEPS))","") $(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c else $(DIR_DEPS)/%.dep : %.c endif @echo "Creating $@ ..." @set -e;\ $(CC) -MM -E $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g' > $@ clean : $(RM) $(DIR_DEPS)![]() ![]() func.h #ifndef FUNC_H #define FUNC_H #include "define.h" void foo(); #endiffunc.c #include "stdio.h" #include "func.h" void foo() { printf("void foo():%s\n",HELLO); }main.c #include "stdio.h" #include "func.h" extern void foo(); int main() { foo(); return 0; }makefile .PHONY : all clean MKDIR := mkdir RM := rm -rf CC := gcc DIR_DEPS := deps DIR_EXES := exes DIR_OBJS := objs DIRS:= $(DIR_DEPS) $(DIR_EXES) $(DIR_OBJS) EXE := app.out EXE := $(addprefix $(DIR_EXES)/,$(EXE)) SRCS := $(wildcard *.c) OBJS := $(SRCS:.c=.o) OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS)) DEPS := $(SRCS:.c=.dep) DEPS := $(addprefix $(DIR_DEPS)/,$(DEPS)) all : $(DIR_OBJS) $(DIR_EXES) $(EXE) ifeq ("$(MAKECMDGOALS)","all") -include $(DEPS) endif ifeq ("$(MAKECMDGOALS)","") -include $(DEPS) endif $(EXE) : $(OBJS) $(CC) -o $@ $^ @echo "Success! Target => $@" $(DIR_OBJS)/%.o : %.c $(CC) -o $@ -c $(filter %.c,$^) $(DIRS) : $(MKDIR) $@ ifeq ("$(wildcard $(DIR_DEPS))","") $(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c else $(DIR_DEPS)/%.dep : %.c endif @echo "Creating $@ ..." @set -e;\ $(CC) -MM -E $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' > $@ clean : $(RM) $(DIRS)![]() |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |