C makefile跳过了隐式规则?

C makefile跳过了隐式规则?,c,makefile,C,Makefile,我有一个用于编译一些C源文件的Makefile,并将输出放在不同的构建目录中,它看起来有点像下面的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 $

我有一个用于编译一些C源文件的Makefile,并将输出放在不同的构建目录中,它看起来有点像下面的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 \
我没有规则来制作
$(对象)
。有趣的是,当我第二次创建这个目标时,我没有得到这个makefile错误,我得到了共享库

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


我不明白为什么只有在第二次运行makesharedlibrary时才执行该模式,make分两个阶段执行。在第一阶段,它检查哪些目标已过时,需要更新。在第二阶段,它执行更新目标的命令。这意味着它会在实际复制源文件之前检查对象文件是否是最新的

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

关于这个问题,有一些很好的读物。

引用:

# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
  gcc -fPIC $< -o $@
左侧的模式通过将对象的
$(SRCDIR)
部分重写为
$(OBJDIR)
来匹配您在
对象中计算的任何一个对象文件模式

顺便说一下,看看这个模式规则如何轻松地执行反向重写?左侧的匹配将转换为右侧的
.c
先决条件。查看规则如何不使用
notdir
addprefix
?您可以在计算
对象时执行相同的操作(相反)。放下
notdir
addprefix
并使用单个
patsubst
变换每个路径

此外,我还消除了重复的
通配符。首先获取
,然后从源计算
对象


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

除了下面的答案指出的内容外,如果您使用多个作业(
-j
),您的生成文件也会中断;不能保证先决条件是按顺序执行的,如果一个先决条件依赖于另一个先决条件,那么就在makefile中表达出来。这一点很好。我将添加所有依赖项有些规则不将其目标声明为其目标,或将其依赖项声明为其依赖项,因此,
make
检查规则是否必须运行不能正常工作。因此,在阅读文档后,我可以得出结论:OBJDIR=/home/test/alpha和SRCDIR=/home/test/beta,它们的右侧将延迟扩展。$(对象)不会在第一次运行makefile时展开,只会在第二次运行时展开。关键信息位于底部,
规则定义
。立即检查规则
sharedLibrary:copySourcesOver linkSources
。检查
linkSources
不会导致任何操作,因为文件是最新的(请记住,更新的文件尚未复制),而检查
copySourcesver
会导致任何更新的源文件的副本。第一个目标copySourcesver会将源文件复制到对象目录。是的,我同意,我已将其更改为静态模式规则,$(对象):%.o:%.c是否可以在对象目录根本不存在的情况下运行Makefile?请问一个问题,什么是反向重写?“反向重写”与规则的作用相反:规则与左侧的.o模式与目标匹配,然后将其重写为右侧的.c先决条件。这与您从源计算.o对象时所做的操作相反。基本上,模式规则是执行
patsubs(leftpat、righpat、target)
。不,在这种情况下,对象目录预先存在,这是makefile变量OBJDIR。我明白你的意思,我会在另一个不同的地方做同样的事情
# pattern
$(OBJECTS)/%.o : $(OBJECTS)/%.c
  gcc -fPIC $< -o $@
$(OBJDIR)/%.o : $(SRCDIR)/%.c