我有一个带有递归调用的makefile。当我第一次运行make时,会创建目标文件并将其链接得很好。但是当我修改源文件并再次运行make时,不会重新创建对象(make表示目标是最新的)。我需要运行make clean
然后运行make。这是我的makefile的简化版本,我认为包含所有相关信息:
PCC = mpicc
#Locations
OBJDIR = ./objects
#Compiler and linker flags
FLAGS = -g -lm
#Object files
SHAREDOBJS = $(addprefix $(OBJDIR)/,shared1.o shared2.o)
SPECIFICOBJS = $(addprefix $(OBJDIR)/,specific1.o specific2.o)
#How to compile and link
$(OBJDIR)/%.o: %.c
$(PCC) -c $*.c $(EXTRA_FLAGS) -o $(OBJDIR)/$*.o
PROGNAME:
$(MAKE) $(MAKEFLAGS) EXTRA_FLAGS="$(FLAGS)" PROGNAME_TARGET
PROGNAME_TARGET: $(SHAREDOBJS) $(SPECIFICOBJS)
$(PCC) $(SHAREDOBJS) $(SPECIFICOBJS) $(EXTRA_FLAGS) -o PROGNAME
第一次运行make PROGNAME
编译就好了。但第二个返回make: "PROGNAME" is up to date.
在我看来,永远不会进行递归调用。例如,如果我在调用make之前添加echo
,则stdout
中不会显示任何内容。
为什么会这样?为什么在递归调用中没有检查源文件的时间戳?我不明白为什么递归破坏了对源文件的依赖。
提前致谢。
答案 0 :(得分:3)
目标PROGNAME
没有先决条件。
第一次make PROGNAME
时,Make看到没有这样的文件,因此它执行规则。
第二次(在您修改shared1.o
之后),Make看到PROGNAME
已经存在,并且目标没有先决条件,因此它看不需要重建目标。它不知道PROGNAME
取决于shared1.o
,因为您没有告诉它。
解决这个问题的方法不止一种。我建议你完全取消递归并使用target-specific variable value:
PROGNAME: EXTRA_FLAGS="$(FLAGS)"
PROGNAME: PROGNAME_TARGET
(您的目标名称可以改进,但可以等待。)