Makefile 关于GNU生成依赖文件*.d
在程序的makefile中,必须编写规则来定义每个对象文件的依赖关系。考虑对象文件<代码>文件。很明显,此对象文件依赖于源文件Makefile 关于GNU生成依赖文件*.d,makefile,gnu-make,Makefile,Gnu Make,在程序的makefile中,必须编写规则来定义每个对象文件的依赖关系。考虑对象文件文件。很明显,此对象文件依赖于源文件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 file
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
请注意,该规则没有配方。可以向其中添加一个配方,但严格来说这不是必需的,因为GNU make可以依赖一个隐式规则(带有配方)将*.c
文件编译成*.o
文件
无论如何,手工编写这样的规则是一项可怕的任务。想象一下,如何使makefile规则与源代码中的#include语句保持同步
GNU make手册在第4.14章“自动生成先决条件”中描述了自动化此过程的方法。该过程首先为每个源文件生成*.d
文件。我引述:
对于每个源文件name.c都有一个makefilename.d,其中列出了目标文件name.o所依赖的文件
手册的内容如下:
下面是从名为name.C的C源文件生成名为name.d的先决条件文件(即makefile)的模式规则:
%.d:%.c
@set-e;rm-f$@\
$(CC)-M$(CPPFLAGS)$<>$@.$$$\
sed's,\($*\)\.o[:]*,\1.o$@:,g'<$@.$$>$@\
rm-f$@$$$$
遗憾的是,手册没有详细解释这条规则实际上是如何工作的。是的,它给出了所需的名称.d文件,但为什么?这条规则很模糊
当看到这个规则时,我感觉它的配方只能在Linux上顺利运行。我说得对吗?有没有办法让这个菜谱也能在Windows上正确运行
非常感谢您的帮助:-)退出所有错误
@set -e;
删除现有的dep文件($@
=target=%.d
)
让编译器生成dep文件,并将其输出到一个临时文件,该临时文件使用shell pid进行后期修复($
->pid) 删除临时部门$$
让我们插入rm -f $@.$$$$
、foo
和CC=gcc
,看看make完成扩展后会发生什么: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.$$
请注意,这是一种非常过时的生成依赖项的方法,如果您使用的是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)
指令允许您在不同的目录中运行make,并在那里创建文件,例如vpath
响应K Mulier: 试试:gmake-C$workdir。。。 这将设置CURDIR=${workdir},但只剩下$PWD(来自env)。 所有临时/输出文件都是在${workdir}中创建的。 此外,我还设置了变量$${PWD}并使用它指定与运行gmake的目录(即源目录)相关的任何内容。 因此,与其 CPPFLAGS += -I../include CPPFLAGS+=-I../include 有 CPPFLAGS += -I$. -I$./../includemake-f path/to/source/Makefile
CPPFLAGS+=-I$-我$./../includeow,非常感谢你的解释。我仍在仔细阅读你的解释,以便完全理解。但是你确实给了我很大的帮助:-)我确实在使用GCC编译器。那么有没有一种更优雅的方法来生成依赖项呢?你能描述一下吗?我有点不好意思问这个问题,因为我知道这可能会占用你很多时间。但我非常感激:-)@K.Mulier添加了一个简短的示例。哇,非常感谢您提供了这个示例。不幸的是,我想“在源代码树之外构建”。这样,我就可以保持源文件夹的整洁。但老实说,我不知道如何生成依赖项,有几种方法可以“在源代码树之外”生成—在源代码树中生成时,将路径放在.o和.d文件的其他位置,或者在源代码树中使用VPATH或路径,并在纯对象树中生成。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.$$
foo.o foo.d : foo.c foo.h someheader.h
gmake -C $workdir ... CURDIR = ${workdir} CPPFLAGS += -I../include CPPFLAGS += -I$. -I$./../includeobjs := 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)