在Makefile中处理多个源文件扩展名

7
我有一个C++项目,其中源文件扩展名为.cpp、.c、.cc,头文件扩展名为.hpp、.h、.hh。源文件位于名为SRC的目录中,而头文件则可预测地位于名为INC的目录中。
我想要编译源文件,并希望使用类似以下规则的方式:
vpath %.c $(SRC)

%.o: %.c
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)

当然,如果我知道源文件的格式将为%.c,则此方法有效,但在可能存在多个文件扩展名的情况下,我还需要构建类似于%.cpp和%.cc的规则。当然,编写三个规则并不是什么大问题,但能够将此makefile用作任何项目的拖放功能,甚至在不同语言中使用,而无需重写规则,这将是很好的。那么,我该如何编写一个规则(或其他实现相同目标的结构),以实现以下功能:
SRC_EXT = cpp c cc
vpath %.$(SRC_EXT) $(SRC)

%.o: %.$(SRC_EXT)
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)

感谢您的帮助。
1个回答

4

标准的POSIX make无法实现此功能。但是,由于你提到了vpath,我假设你正在使用GNU make。如果你有足够新的版本(3.81或更新版本),你可以通过调用和评估轻松地完成此操作:

SRC_EXT = cpp c cc

define compile_rule
%.o : %.$1
        $$(COMPILER) $$(FLAGS) $$< $$(INCFLAG)$$(INC)
endef    
$(foreach EXT,$(SRC_EXT),$(eval $(call compile_rule,$(EXT))))

如果您没有足够新的 GNU make 或更喜欢替代方案,您可以使用生成的 Makefile 来完成相同的事情。


啊哈!太好了!我一直在想如何调用编译规则,但是foreach首先是如何被调用的呢?它只是坐在文件里面吗,就像在设置SRC_EXT变量之后立即被调用一样吗?这会强制重新编译所有源文件,即使.o文件已经是最新的吗? - user487100
1
Makefile解析的关键在于扩展。每当make在“立即上下文”(请参阅GNU make手册中的“How Make Reads a Makefile”)中遇到变量或函数时,它将对其进行扩展。这可能涉及许多步骤。扩展完成后,剩下的内容将被解析为makefile。eval函数是特别的。基本上,当读取makefile时,此foreach循环会被make扩展和解析,并以与编写规则相同的方式定义规则。因此,它的行为就像任何其他make规则(不会强制重新编译)。 - MadScientist
我不明白EXT是什么意思,有人能解释一下吗?编辑:算了,看起来它是for循环中的i - ihsoy ih

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接