在程序的makefile中,必须编写定义每个目标文件的依赖关系的规则.考虑目标文件fileA.o.很明显,此目标文件取决于源文件fileA.c.但它也将取决于此源文件包含的所有头文件.因此,应将以下规则添加到makefile中:
# This rule states that fileA.o depends on fileA.c (obviously), but also
# on the header files fileA.h, fileB.h and fileC.h
fileA.o: fileA.c fileA.h fileB.h fileC.h
Run Code Online (Sandbox Code Playgroud)
请注意,该规则没有配方.可以添加一个配方,但严格来说并不是必需的,因为GNU make可以依赖一个隐式规则(带配方)将*.c文件编译成*.o文件.
无论如何,手动编写这样的规则是一项地狱般的任务.想象一下使makefile规则与源代码中的#include语句保持同步的工作.
GNU make手册在第4.14章"自动生成先决条件"中描述了一种自动执行此过程的方法.该过程从*.d为每个源文件生成文件开始.我引用:
对于每个源文件name.c,都有一个makefile name.d,它列出了目标文件name.o所依赖的文件.
手册进行:
这里是规则图案产生的前提条件的文件(即,生成文件)称为name.d从称为C源文件name.c:
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
Run Code Online (Sandbox Code Playgroud)
遗憾的是,该手册没有详细解释这条规则是如何实际运作的.是的,它提供了所需的name.d文件,但为什么呢?该规则非常混淆..
在查看此规则时,我感觉它的配方只能在Linux上顺利运行.我对吗?有没有办法让这个配方在Windows上正确运行?
任何帮助是极大的赞赏 :-)
use*_*267 10
退出所有错误
@set -e;
Run Code Online (Sandbox Code Playgroud)
删除现有的dep文件($@= target = %.d)
rm -f $@;
Run Code Online (Sandbox Code Playgroud)
让编译器生成dep文件并输出到后缀为pid的临时文件($<= first prerequisite = %.c,$$$$- > $$- > pid)
$(CC) -M $(CPPFLAGS) $< > $@.$$$$;
Run Code Online (Sandbox Code Playgroud)
捕获目标匹配$*.o($*= match stem = %),将其替换为目标,然后依赖于依赖文件本身,输出到dep文件
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
Run Code Online (Sandbox Code Playgroud)
删除temp dep
rm -f $@.$$$$
Run Code Online (Sandbox Code Playgroud)
让我们插上foo,CC = gcc和CPPFLAGS = ''看化妆完成扩大后的东西会发生什么:
foo.d: foo.c
@set -e; rm -f foo.d; \
gcc -M foo.c > foo.d.$$; \
sed 's,\(foo\)\.o[ :]*,\1.o foo.d : ,g' < foo.d.$$ > foo.d; \
rm -f foo.d.$$
Run Code Online (Sandbox Code Playgroud)
shell本身将扩展$$为pid,dep文件中的最终规则将类似于
foo.o foo.d : foo.c foo.h someheader.h
Run Code Online (Sandbox Code Playgroud)
请注意,这是一种非常过时的生成依赖关系的方法,如果您使用GCC或clang,则可以将其作为编译本身的一部分生成CPPFLAGS += -MMD -MP.
假设您有一个名为的程序foo:
objs := foo.o bar.o
deps := $(objs:.o=.d)
vpath %.c $(dir $(MAKEFILE_LIST))
CPPFLAGS += -MMD -MP
foo: $(objs)
.PHONY: clean
clean: ; $(RM) foo $(objs) $(deps)
-include $(deps)
Run Code Online (Sandbox Code Playgroud)
这就是你所需要的,内置规则将完成其余的工作.显然,如果您希望将对象文件放在不同的文件夹中,或者您希望在源树之外构建,那么事情会更复杂一些.
该vpath指令允许您在不同的目录中运行make并在那里创建文件,例如make -f path/to/source/Makefile.
| 归档时间: |
|
| 查看次数: |
5892 次 |
| 最近记录: |