我正在尝试从以下规则定义的要编译的文件列表中排除 main.cpp 文件:
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
ifneq ($(notdir $<), main.cpp)
@$(COMPILE.cpp) $(OUTPUT_OPTION) $<
endif
这个'ifneq'条件总是计算为true,这很奇怪。我究竟做错了什么?有没有更好的方法从显式规则中排除一个文件?
答案 0 :(得分:11)
如果您使用的是GNU Make,为什么不尝试使用filter-out
text function。
返回文本中与任何模式单词不匹配的所有以空格分隔的单词,删除与一个或多个匹配的单词。这与过滤功能完全相反。
例如,给定:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
以下内容生成一个列表,其中包含不在“主电源”中的所有目标文件:
$(filter-out $(mains),$(objects))
答案 1 :(得分:5)
这不是最好的方法,但是如果按照这些方式执行,请将其写为shell条件,而不是使用GNU make条件:
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
@if [ $(notdir $<) != main.cpp ]; \
then $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
fi
需要延续标记(反斜杠)。用分号也是如此。在调用shell以解释它们之前,前缀为$
的值将被make
扩展。你可能也不希望回声在哪里。你可能需要:
$(TMPDIRPATH)%.o: %.cpp
@if [ $(notdir $<) != main.cpp ]; \
then echo compile $<; \
$(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
fi
我希望这样做的方法是使用要编译的文件列表。使用任何通配符机制会在添加额外文件时导致问题 - 其他测试或实际上不属于系统的杂散文件。
评论说“但GNU制作手册说ifneq
应该有效。”
如果ifneq
位置正确,ifneq (${CFLAGS}, -Wall)
CFLAGS += -Wall
endif
file1.o: file1.c
${CC} ${CFLAGS} -c $<
将起作用,这意味着'不会缩进作为与规则关联的命令的一部分'。因此,你可以写一些类似的东西(一个令人震惊的坏榜样,但我的大脑就是这样的):
ifneq
但是当make
在问题中缩进时,它只是在{{1}}运行shell来处理命令时实际上在系统上找不到的命令。
答案 2 :(得分:5)
当make启动并解析makefile时,ifneq
行只被评估一次。在这种情况下,$<
是空的。
要为您的模式规则匹配的每个目标获得不同的行为,您可以执行类似
的操作$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
@$(if $(filter main.cpp,$<),$(COMPILE.cpp) $(OUTPUT_OPTION) $<)
可能会让您想到makefile中ifneq
和$(if)
之间的区别,就像C代码中#if
和if()
之间的区别一样。
退一步说:如果您不希望此规则编译main.cpp
,那么您可能希望提供一个以$(TMPDIRPATH)main.o
为目标的显式规则,这将是始终优先考虑模式规则。或者,如果您不希望$(TMPDIRPATH)main.o
完全 ,那么您应该在:
的正确视线上查找具有该规则的规则,然后将其删除从那里。
答案 3 :(得分:2)
Make并不是一个很好的方法来处理规则中的条件。您可以将条件放在命令中,但在这种情况下,有一种更清洁的方式:
$(TMPDIRPATH)main.o:
@echo compile $< (but not really)
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
@$(COMPILE.cpp) $(OUTPUT_OPTION) $<
修改:
我没有意识到你没有拥有一个main.cpp
。解决方案很简单:删除main.cpp
作为main.o
规则的先决条件(我已将其删除)。现在makefile不需要它,也不会尝试构建它。
但是你仍在运行规则,这意味着某些东西仍在尝试构建main.o
,作为显式目标或其他内容的先决条件。这是一种混淆的症状,对makefile的这种改变将无法解决。如果您告诉我们更多有关情况的信息,也许我们可以提出更好的解决方案。是什么要求main.o
?你有main.o
吗?当你打电话给Make时,你指定了什么目标?