我有一个运行二进制文件的makefile来生成cpp文件。然后我编译cpp文件并为每个cpp文件生成.o文件。
问题是当首次调用makefile时,该文件夹为空,因为尚未调用二进制文件并且
CPP_FILES=$(wildcard $(MY_DIR)/inc/output/*.cpp)
将是一个空变量。
所以我将行改为
CPPFILES=$$(wildcard $(MY_DIR)/inc/output/*.cpp)
OBJFILES=$$(patsubst $(MY_DIR)/*.cpp,$(MY_DIR)/*.o,$(CPPFILES))
和
//运行二进制文件以生成cpp文件
.SECONDEXPANSION:
libEXP.so:$(CPPFILES),$(OBJFILES)
$(CC) $(CFLAGS) -I(INC) -L(LIBS) -shared -o $(OBJFILES) $@
二级扩展失败,说shell无法找到通配符命令 我做错了什么?
答案 0 :(得分:3)
你遇到的问题是make始终从最终目标BACKWARDS到源,然后再次开始构建和解决先决条件。从库开始,然后看看它的先决条件是什么,然后看看那些先决条件是什么,然后是THOSE的先决条件等等。
因此,当make扩展$(OBJFILES)
值时,即使您通过第二次扩展延迟它,仍然会出现.cpp文件尚未创建的情况。
你必须解释一下,有一个规则可以生成.cpp文件。一旦了解了,它将为您调用您的规则。但是,您将无法使用通配符来确定要构建的.cpp文件,除非您想要首先构建所有.cpp文件,然后以递归方式调用make。
修改强>
你问为什么第二次扩张不起作用。我在第一段中提到过这一点,但可能还不够清楚。制作经历两个阶段的处理。首先它读取makefile,然后它运行规则并构建东西。二级扩展步骤会延迟解决,直到第二步......但在这种情况下,这不会对您有所帮助。
你要make make来构建libEXP.so。要做到这一点,它需要扩展libEXP.so的先决条件,以便它知道目标所依赖的内容。 THIS 是执行第二次扩展的时候,但是我们还没有构建任何.cpp文件,因为我们不知道我们需要它们,所以通配符扩展为空。 Make将不会创建那些.cpp文件,直到它知道它需要它们,并且它不知道它需要它们直到它已经拥有它们所以它可以为libEXP.so的先决条件生成.o文件列表。这显然不起作用:))
答案 1 :(得分:1)
要明确说明:不应对生成的文件使用$(wildcard )
。如果你想要一个“所有生成文件的列表”,$(wildcard )
只会通过运气给你这个列表(如果已经生成了所有文件)。
如果生成器文件和生成的文件之间存在一对一的对应关系,那么您可以在生成器文件上使用$(wildcard)
并转换结果。
以Google的协议缓冲区为例(它可以从.proto文件生成.cc文件)
PROTOSS := $(wildcard *.proto)
GENERATED_SOURCES := ${PROTOSS:.proto=.cc}
GENERATED_HEADERS := ${PROTOSS:.proto=.h}
答案 2 :(得分:0)
将CPPFILES
和OBJFILES
保留为通常的递归变量:
CPPFILES = $(wildcard $(MY_DIR)/inc/output/*.cpp)
OBJFILES = $(CPPFILES:%.cpp=%.o)
并推迟扩展,使用双倍美元如下:
.SECONDEXPANSION:
libEXP.so: $$(OBJFILES)
$(CC) $(CFLAGS) -I(INC) -L(LIBS) -shared -o $(OBJFILES) $@
但我想问题是在运行cpp文件生成器之前发生了扩展。你怎么调用它?是规则还是其他什么?
答案 3 :(得分:0)
我遇到了这种情况。我尝试了几层间接(使用一个称为使用wildcard
的固定序列的固定序列),但是在执行生成文件的配方之前,make总是评估通配符。我的解决方案是编写一个Perl脚本来收集文件列表并执行我需要对它们执行的操作,然后从makefile调用脚本。我只希望我早点完成。我一直在想我想避免引入额外的文件,但总的来说,使用脚本比使用非常重要的makefile配方更容易,它可以节省大量时间来完成开始。
答案 4 :(得分:0)
另一种选择是在bash中使用for循环:
target: prereqs
for file in files/*; do \
... \
done