使用自动生成的* .d文件更改依赖项x.h时,*。c不会消失

时间:2019-01-03 15:55:30

标签: makefile gnu-make

在编译过程中处理依赖文件时遇到一个问题。我只是给您我在项目中遇到的情况。

我有两个名为a.cb.c的C源文件,其中包括一个名为c.h的头文件。我运行了makefile,其中包含编译两个文件的说明。我可以成功编译a.c文件,但是在编译b.c时遇到了一些失败,这需要对c.h进行一些更改才能解决该问题。在c.h中进行更改并触发构建(增量构建)之后,a.c文件也应该再次编译,对吗?因为a.c也依赖于c.h文件。

我遵循了所有依赖机制(创建自动依赖文件,包括.d文件等)

DEPSALL := $(wildcard $(patsubst %,%.d,$(basename $(TGTFILES)/*.c)))
-include $(DEPSALL)
$(TGTFILES)/%.o: $(TGTFILES)/%.c
        mkdir -p $(@D)
        $(CC64) -MT $@ -MMD -MP -MF $(patsubst %,%.d,$(basename $@)) -o $(@) -c $(CFLAGS64) $<
  ...
  ...

我在这里错过了什么吗?我想重建所有.c文件,其中包括我更改过的特定头文件。

2 个答案:

答案 0 :(得分:1)

您的问题是不完整的:您并未真正描述所面临的问题(但是我们可能会猜测目标文件并未按期重建),并且显示的Makefile部分不足以了解您的目标是。

首先,此表达式:

DEPSALL := $(wildcard $(patsubst %,%.d,$(basename $(TGTFILES)/*.c)))

毫无用处。等效于更简单易懂的内容:

DEPSALL := $(wildcard $(TGTFILES)/*.d))

类似地,在您的编译配方中,您可以替换:

$(patsubst %,%.d,$(basename $@))

作者:

$(TGTFILES)/$*.d

但是,让我们回到您的主要问题(至少我想这是您的主要问题):在修改头文件时,某些目标文件并没有得到应有的重建。

我的猜测是您认为:

DEPSALL := $(wildcard $(patsubst %,%.d,$(basename $(TGTFILES)/*.c)))

将为依赖性文件列表分配给DEPSALL,每个源文件一个,就像其他形式一样:

DEPSALL := $(patsubst %.c,%.d,$(wildcard $(TGTFILES)/*.c))

如果这就是您的想法,那么您错了。您的版本将在调用make时为DEPSALL当前存在的依赖文件列表分配给$(TGTFILES)。如果某些(或全部)丢失,则将不会重建某些目标文件...

我建议您仔细阅读this excellent post about Auto-Dependency Generation。如果您将其调整为适合您的设置,则应该以类似以下内容结束:

TGTFILES := tgtfiles
SRCS     := $(wildcard $(TGTFILES)/*.c)
OBJS     := $(patsubst %.c,%.o,$(SRCS))
DEPS     := $(patsubst %.c,%.d,$(SRCS))
INCLUDES := include
CFLAGS   += -I$(INCLUDES)

.PHONY: objs clean

objs: $(OBJS)

%.o: %.c
%.o: %.c %.d
    $(CC) -MT $@ -MMD -MP -MF $*.Td $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
    @mv -f $*.Td $*.d && touch $@

%.d: ;
.PRECIOUS: %.d

clean:
    rm -f $(OBJS) $(DEPS)

include $(DEPS)

几个方面可能看起来很奇怪,毫无用处,甚至完全是错误的。但是,如果您仔细阅读上述文章,您会发现它完全有意义。演示:

$ tree
.
├── Makefile
├── include
│   └── c.h
└── tgtfiles
    ├── a.c
    └── b.c

2 directories, 4 files
$ make
cc -MT tgtfiles/b.o -MMD -MP -MF tgtfiles/b.Td -Iinclude  -c -o tgtfiles/b.o tgtfiles/b.c
cc -MT tgtfiles/a.o -MMD -MP -MF tgtfiles/a.Td -Iinclude  -c -o tgtfiles/a.o tgtfiles/a.c
$ tree
.
├── Makefile
├── include
│   └── c.h
└── tgtfiles
    ├── a.c
    ├── a.d
    ├── a.o
    ├── b.c
    ├── b.d
    └── b.o

2 directories, 8 files
$ cat tgtfiles/a.d
tgtfiles/a.o: tgtfiles/a.c include/c.h

include/c.h:
$ make
make: Nothing to be done for 'objs'.
$ touch include/c.h 
$ make
cc -MT tgtfiles/b.o -MMD -MP -MF tgtfiles/b.Td -Iinclude  -c -o tgtfiles/b.o tgtfiles/b.c
cc -MT tgtfiles/a.o -MMD -MP -MF tgtfiles/a.Td -Iinclude  -c -o tgtfiles/a.o tgtfiles/a.c

答案 1 :(得分:0)

wildcard函数应用程序看起来不正确。应该是:

DEPSALL := $(patsubst %,%.d,$(basename $(wildcard $(TGTFILES)/*.c)))