添加依赖项会将目标更改为第一个C文件

时间:2012-03-12 14:38:16

标签: makefile gnu-make

考虑以下makefile:

.SUFFIXES:

SRC:=../Src
OBJ:=../Obj

# Sources
SOURCES := $(SRC)/App/a.c $(SRC)/App/b.c $(SRC)/App/c.c
HEADERS := $(wildcard $(SRC)/App/*.h)

# Directories
INC_DIRS := $(SRC)/App
OBJ_INC_DIRS := $(INC_DIRS:$(SRC)/%=$(OBJ)/%)

# Objects
OBJECTS := $(SOURCES:$(SRC)%=$(OBJ)%.obj)

# Dependencies
DEPS := $(SOURCES:$(SRC)%.c=$(OBJ)%.d)
-include $(DEPS)

GCC_INCLUDES := $(foreach directory, $(INC_DIRS), -I$(directory))

all: target

target: $(OBJECTS)
    touch target

#Objects
$(OBJ)%.c.obj: $(SRC)%.c
    @echo Compiling $@
    @touch $@

# Dependencies 
$(OBJ)%.d: $(SRC)%.c
    @echo Checking dependencies for $<
    @gcc -MM $< $(GCC_INCLUDES) -MT '$(patsubst %.d,%.c.obj,$@)' -MT '$@' -MF '$@'
    @[ ! -s $@ ] && rm -f $@

# Creating directory tree before checking dependencies    
$(DEPS):|$(OBJ_INC_DIRS)

$(OBJ_INC_DIRS):
    @mkdir $@

clean:
    echo clean
    @rm $(OBJ_INC_DIRS)

第一次跑步时,我得到:

Checking dependencies for ../Src/App/a.c
Checking dependencies for ../Src/App/b.c
Checking dependencies for ../Src/App/c.c
clean
Compiling ../Obj/App/a.c.obj
Compiling ../Obj/App/b.c.obj
Compiling ../Obj/App/c.c.obj
touch target

没关系,但现在再次制作(不修改任何文件):

make: `../Obj/App/a.c.obj' is up to date.

现在,如果我修改文件a.c

Checking dependencies for ../Src/App/a.c
Compiling ../Obj/App/a.c.obj

target未重新制作!

这就像我的文件a.c是目标,但它不是......有人可以解释我这里有什么问题吗?

如果我将包含删除到DEPS,我会观察到预期的行为......

由于


修改

通过将@Beta所提到的包含放在最后,但现在我添加了目标clean并显示结果......

1 个答案:

答案 0 :(得分:1)

我必须做一些实验才能确定,但​​我认为问题是:

-include $(DEPS)
...
all: target

您在第一个目标之前加入$(DEPS) 。因此,如果您修改a.c,Make会发现它必须重建a.d,那么因为它includes该文件必须重新开始,现在a.c.obj是早于all的目标{1}}。

尝试将-include $(DEPS)移动到makefile的末尾。

修改:
(两个小点:您的clean规则不正确,因为它会尝试rm一个目录,而我会make clean; make all而不是make all,因为我不确定承诺在所有情况下按给定顺序构建目标。)

是的,即使在运行DEPS时,此makefile也会重建clean。 makefile includes这些文件并且有一个规则,所以如果它们丢失或过时,它必须重建它们并重新启动,无论目标是什么。解决这个问题的最佳方法是Advanced Auto-Dependency Generation;基本上,构建依赖项文件的命令都在%.obj规则中,因此a.d是构建a.c.obj的副作用。这是一项复杂的技术,并不明显,但它的工作效果非常好。 (如果您尝试此操作并且无法进行设置,请告诉我们。)