Makefile 第二个扩展:在GNU函数调用之前评估模式规则
我的Makefile 第二个扩展:在GNU函数调用之前评估模式规则,makefile,gnu,Makefile,Gnu,我的makefile中对每个对象文件都有一条规则。相应的源文件和隐藏的依赖项文件是先决条件 示例: obj/test/bar.o:src/test/bar.c src/test/.bar.d 由于可能有大量的对象文件,我想概括一下这个规则。我的第一次尝试是: $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $(dir $(SRCDIR)/%.$(DEPSEXT)).$(notdir $(SRCDIR)/%.$(DEPSEXT)) 与 问题是第二个
makefile
中对每个对象文件都有一条规则。相应的源文件和隐藏的依赖项文件是先决条件
示例:
obj/test/bar.o:src/test/bar.c src/test/.bar.d
由于可能有大量的对象文件,我想概括一下这个规则。我的第一次尝试是:
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $(dir $(SRCDIR)/%.$(DEPSEXT)).$(notdir $(SRCDIR)/%.$(DEPSEXT))
与
问题是第二个先决条件中的模式规则在应用了dir
和notdir
之后进行计算。因此,上述示例的第二个先决条件是/src/.test/bar.d
,而不是/src/test/.bar.d
作为替代方案,我尝试使用以下shell命令生成正确的先决条件:
%.$(OBJEXT): $(shell echo %.$(SRCEXT) | sed -e 's/^[^\/]*/src/') $(shell echo %.$(SRCEXT) | sed -e 's/^[^\/]*/src/;s/^\(.*\/\)/\1./')
我正在使用sed
对对象文件执行字符串替换。正则表达式经过测试并正确无误。虽然wildecard%
对echo
可见,但我无法将其导入sed
。因此,sed
接收空字符串并输出“错误”结果
问题:
echo
会看到%
,但为什么不可能将其导入sed
使用
shell
函数不起作用的原因与使用dir
等不起作用的原因完全相同。它们都是make函数,并且它们都以相同的方式扩展,那么为什么其中一个可以工作而另一个不能呢
您遇到的问题是,在解析makefile时,规则介绍行由make展开。但模式规则直到很久以后才被应用,当make尝试实际构建规则时。make解析makefile时,它完全不知道%
将扩展到什么:在应用规则之前,该扩展不会完成
因此,在所有情况下,make函数(包括shell
)都是在文本字符%
上运行的
通常,依赖项文件被放在不同的目录中,而不是操纵文件名,例如.deps/foo.d
,以避免这些类型的问题
但是,您可以按如下方式执行所需操作:
.SECONDEXPANSION:
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $$(dir $(SRCDIR)/$$*.$(DEPSEXT)).$$(notdir $(SRCDIR)/$$*.$(DEPSEXT))
这就是我要找的。非常感谢。如果将依赖项文件存储在专用(隐藏)文件夹中,是否还会重建源文件夹的目录结构?否则,.deps文件夹中可能会出现两个同名的.d文件。示例:src/foo.c和src/test/foo.cYes,确切地说:您将拥有相同的结构。无论如何,您都必须这样做,因为前提条件必须是
$(DEPDIR)/%.$(DEPSEXT)
您不应该使用shell表达式,因为它效率低下。但是如果出于某种原因想使用它,则必须将其放入一个变量中,如DEPNAME=$$(shell…
(注意不要使用:=
),然后添加$(DEPNAME)
,作为先决条件。或者,您可以创建一个宏,如MAKEDEP=$(shell echo$1.$(SRCEXT)…
,然后添加$$(call MAKEDEP,$$*)
作为先决条件。我已将我的案例移至一个新问题。
.SECONDEXPANSION:
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $$(dir $(SRCDIR)/$$*.$(DEPSEXT)).$$(notdir $(SRCDIR)/$$*.$(DEPSEXT))