我试图从下面的规则定义的要编译的文件列表中排除main.cpp文件:
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
ifneq ($(notdir $<), main.cpp)
@$(COMPILE.cpp) $(OUTPUT_OPTION) $<
endif
Run Code Online (Sandbox Code Playgroud)
这个'ifneq'条件总是计算为true,这很奇怪.我究竟做错了什么?有没有更好的方法从显式规则中排除一个文件?
Ven*_*hav 12
如果您正在使用GNU Make,为什么不尝试使用filter-out文本功能.
返回文本中与任何模式单词不匹配的所有以空格分隔的单词,删除与一个或多个匹配的单词.这与滤波器功能完全相反.
例如,给定:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
Run Code Online (Sandbox Code Playgroud)
以下代码生成一个列表,其中包含不在'mains'中的所有目标文件:
$(filter-out $(mains),$(objects))
Run Code Online (Sandbox Code Playgroud)
这不是最好的方法,但是如果按照这些方式进行,请将其写为shell条件,而不是使用GNU make conditionals:
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
@if [ $(notdir $<) != main.cpp ]; \
then $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
fi
Run Code Online (Sandbox Code Playgroud)
需要连续标记(反斜杠).用分号也是如此.在调用shell以解释它们之前,$将扩展前缀的值make.你可能也不希望回声在哪里.你可能需要:
$(TMPDIRPATH)%.o: %.cpp
@if [ $(notdir $<) != main.cpp ]; \
then echo compile $<; \
$(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
fi
Run Code Online (Sandbox Code Playgroud)
我希望这样做的方法是使用要编译的文件列表.使用任何通配符机制会在添加额外文件时导致问题 - 其他测试或实际上不属于系统的杂散文件.
评论说"但GNU制作手册说ifneq应该有用".
在ifneq如果它被正确地定位,这意味着"没有缩进为与规则相关联的命令的部分"将工作.因此,你可以写一些类似的东西(一个令人震惊的坏例子,但我的大脑是在fritz上):
ifneq (${CFLAGS}, -Wall)
CFLAGS += -Wall
endif
file1.o: file1.c
${CC} ${CFLAGS} -c $<
Run Code Online (Sandbox Code Playgroud)
但是当在问题ifneq中缩进时,它只是在make运行shell来处理命令时实际上在系统上找不到的命令.
ifneq当make启动并解析makefile时,该行仅被评估一次.在这种情况下,$<是空的.
要为您的模式规则匹配的每个目标获得不同的行为,您可以执行类似的操作
$(TMPDIRPATH)%.o: %.cpp
@echo compile $<
@$(if $(filter main.cpp,$<),$(COMPILE.cpp) $(OUTPUT_OPTION) $<)
Run Code Online (Sandbox Code Playgroud)
它可以帮助你思考之间的差异ifneq,并$(if)在makefile像之间的差别#if,并if()在C代码.
但是,退一步说:如果您不希望main.cpp按此规则编译,那么您可能希望提供一个显式规则$(TMPDIRPATH)main.o作为其目标,这将始终优先于模式规则.或者,如果你不想$(TMPDIRPATH)main.o得到由所有,你应该寻找的是有它的右眼前的规则:,并从那里取出.