makefile跳过了隐式规则?

时间:2016-10-20 14:15:20

标签: c makefile

我有一个Makefile用于编译一些C源文件,并将输出放在不同的Build目录中,它看起来有点像下面的makefile:

 OBJDIR=/home/test/alpha
 SRCDIR=/home/test/beta
 # make variable will be exanded when used (and not at declaration)
 OBJECTS:= $(addprefix $(OBJDIR), $(notdir $(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c))))

SOURCES:=$(wildcard $(SRCDIR)/*.c))

.PHONY: copySourcesOver linkSources sharedLibrary
 copySourcesOver: $(SOURCES)
 cp $(SOURCES) $(OBJDIR)/

# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
 gcc -fPIC $< -o $@

linkSources: $(OBJECTS)
 gcc -shared -o libshared.so $@

sharedLibrary: copySourcesOver \
 linkSources \

所以当我运行目标时会发生什么:

make sharedLibrary

我没有制定$(OBJECTS)的规则。有趣的是,当我第二次创建这个目标时,我没有得到这个makefile错误,而且我得到了共享库。

我做了一些研究,我发现Makefile没有扩展PHONY目标的隐式规则,这就是我将linkSources从PHONY目标更改为普通文件的原因。但不幸的是,它并没有解决问题。

我不明白为什么模式只在我第二次运行make sharedLibrary

时执行

2 个答案:

答案 0 :(得分:2)

分两个阶段执行。在第一阶段,它检查哪些目标已过期并需要更新。在第二阶段,它执行更新目标的命令。这意味着它会在实际复制源文件之前检查目标文件是否是最新的。

因此它检查并确定目标文件是最新的,然后将(更新的)源文件复制到$(OBJDIR)

关于这个主题有一些很好的阅读in the docs

答案 1 :(得分:1)

引用:

# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
  gcc -fPIC $< -o $@

这条规则是无稽之谈,因为OBJECTS是一个包含多个单词的变量,而不是一个单独的路径组件;此外,.c源与对象不在同一目录中(整个点)。

我怀疑你想要:

$(OBJDIR)/%.o : $(SRCDIR)/%.c

左侧的图案通过将OBJECTS部分重写为$(SRCDIR)来匹配您在$(OBJDIR)中计算的任何一个目标文件图案。

顺便说一下,看看这种模式规则如何轻松执行反向重写?左侧的匹配将转换为右侧的.c先决条件。了解规则如何不使用notdiraddprefix?在计算OBJECTS时,你可以做同样的事情(反过来)。放弃notdiraddprefix并使用单个patsubst转换每个路径。

另外,我将消除重复的wildcard。首先获取SOURCES,然后从来源计算OBJECTS

最后,当对象目录不存在时,如何在新结账时工作?你需要一些mkdir -p gcc ... -o foo/bar.o不会创建foo目录。