Windows NMake中是否存在与GNU Make filter-out等效的功能?
filter-out及相关问题解决方案 首先明确说:NMake并没有和GNU Make的filter-out完全等价的内置关键字,你遇到的报错正是因为NMake无法识别filter-out里的连字符(它把filter-out当成了一个非法的宏名称)。不过我们可以用NMake的原生语法实现相同的逻辑,同时也帮你解决+=和文件匹配的问题。
1. 实现filter-out的等价逻辑
GNU Make里的OBJS_TEST = $(filter-out $(EXE_OBJ), $(OBJS))作用是从OBJS列表中移除EXE_OBJ对应的项,在NMake里可以通过循环遍历+条件判断来实现:
# 先初始化空的OBJS_TEST OBJS_TEST = # 遍历OBJS中的每个对象 !FOR obj IN ($(OBJS)) ! # 跳过和EXE_OBJ相同的项 ! IF "$(obj)" != "$(EXE_OBJ)" OBJS_TEST = $(OBJS_TEST) $(obj) ! ENDIF !ENDIF
这段代码会逐个检查OBJS里的元素,只把不等于EXE_OBJ的项添加到OBJS_TEST中,和filter-out的效果完全一致。
2. 修复+=与文件匹配问题
你提到+=在NMake中无法生效,其实NMake是支持+=语法的,问题可能出在你用的wildcard——NMake没有内置的wildcard宏,直接写$(wildcard tests/*.cpp)会被当作原始字符串保留,而不是展开成文件列表。
要实现GNU Make中wildcard的效果,我们可以用NMake的!DIR命令来获取文件列表:
# 先获取tests目录下的所有.cpp文件 !DIR /B tests\*.cpp > test_files.tmp # 初始化CPP_TEST并导入文件列表 CPP_TEST = !INCLUDE test_files.tmp # 删除临时文件 !DEL test_files.tmp # 现在可以正常用+=添加额外文件了 CPP_TEST += uiuc\catch\catchmain.cpp
如果不想生成临时文件,也可以用!FOR循环直接遍历文件:
CPP_TEST = !FOR file IN (!DIR /B tests\*.cpp) CPP_TEST = $(CPP_TEST) $(file) !ENDIF CPP_TEST += uiuc\catch\catchmain.cpp
3. 关于你遇到的语法错误
报错fatal error U1001: syntax error : illegal character '-' in macro的原因很直接:NMake的宏名称里不允许出现连字符-,它把filter-out当成了一个宏的名字,自然就报错了。替换成上面的循环逻辑后,这个错误就会消失。
内容的提问来源于stack exchange,提问作者butterflyknife

