过滤Makefile列表中的相邻单词
我需要在gnu makefile中操作一些C标志,我需要从标志中提取一些两个单词参数(例如,过滤Makefile列表中的相邻单词,makefile,gnu-make,Makefile,Gnu Make,我需要在gnu makefile中操作一些C标志,我需要从标志中提取一些两个单词参数(例如,-mllvm,后面跟着空格,然后是一个子参数。我需要删除mllvm和后面的单词) 不幸的是,我没有看到一个直接的方法来做这件事。$(过滤器)不起作用,因为假定搜索参数是一个空格分隔的单词列表,并且模式是多个单词$(patsubst)似乎也不起作用,根据手册页,它: 在匹配模式的文本中查找空格分隔的单词 但我需要匹配多个单词,而不仅仅是单词。我想知道我是否遗漏了一些巧妙的技巧。我想你必须使用递归调用函数。也
-mllvm
,后面跟着空格,然后是一个子参数。我需要删除mllvm
和后面的单词)
不幸的是,我没有看到一个直接的方法来做这件事。$(过滤器)
不起作用,因为假定搜索参数是一个空格分隔的单词列表,并且模式是多个单词$(patsubst)
似乎也不起作用,根据手册页,它:
在匹配模式的文本中查找空格分隔的单词
但我需要匹配多个单词,而不仅仅是单词。我想知道我是否遗漏了一些巧妙的技巧。我想你必须使用递归调用函数。也许是这样的:
removearg = $(if $2,$(if $(filter $1,$(word 1,$2)),$(call removearg,$1,$(wordlist 3,$(words $2),$2)),$(word 1,$2) $(call removearg,$1,$(wordlist 2,$(words $2),$2))))
keeparg = $(if $2,$(if $(filter $1,$(word 1,$2)),$(word 1,$2) $(word 2,$2) $(call keeparg,$1,$(wordlist 3,$(words $2),$2)),$(call keeparg,$1,$(wordlist 2,$(words $2),$2))))
CFLAGS := -DFOO -DBAR -mllvm llvmflag1 -mllvm llvmflag2
OTHER_CFLAGS := $(call removearg,-mllvm,$(CFLAGS))
MLLVM_FLAGS := $(call keeparg,-mllvm,$(CFLAGS))
基本上,removearg检查列表中的第一个单词是否等于第一个参数(-mllvm
),如果是,则从第三个单词开始递归调用,跳过第一个和第二个单词;如果不是,则扩展到第一个单词,然后从第二个单词开始递归调用自己
keeparg函数是相同的,但如果-mllvm
跳过下一个单词,则会扩展到前两个单词
埃塔
实际上,这里有一个更简单的方法:
removearg = $(filter-out $1^%,$(subst $1 ,$1^,$2))
keeparg = $(subst $1^,$1 ,$(filter $1^%,$(subst $1 ,$1^,$2)))
OTHER_CFLAGS := $(call removearg,-mllvm,$(CFLAGS))
MLLVM_FLAGS := $(call keeparg,-mllvm,$(CFLAGS))
这假设您在
CFLAGS
中永远不会有启动-mllvm^
的选项。如果是这样,请选择除^
之外的其他从未存在的字符(如果您想尝试帮助程序库,则碰巧有;)以编程方式解决任务的支持函数:
$(call while, $$(call glob-match,$(space)$$(CFLAGS),*-mllvm *),\
tmp := $$(call glob-match,$(space)$$(CFLAGS),*-mllvm *)$(newline)\
rest := $$(call spc-unmask,$$(word 3,$$(tmp)))$(newline)\
llvm_flg := $$(firstword $$(rest))$(newline)\
CFLAGS := $$(firstword $$(tmp)) $$(call tail,$$(rest))$(newline)\
$$(info [[[$$(tmp) --- $$(rest) --- $$(CFLAGS) ]]])$(newline)\
MLLVM_FLAGS+=$$(llvm_flg),\
MLLVM_FLAGS := $$(strip $$(MLLVM_FLAGS))$(newline)\
CFLAGS := $$(call spc-unmask,$$(CFLAGS))\
)
- 条件:只要glob match在CFLAGS中返回一个-mllvm匹配。有一个小技巧可以避免在第一个*上出现空匹配:我们在字符串的开头插入$(空格)字符,这样匹配就永远不会为空
- 正文(注意换行符的引用-这是$(eval)正确解释代码所必需的):
- 将glob match的输出提取到临时变量中(在该输出中替换空格,请参见glob match)。输出是一个由三个元素组成的列表:从-mllvm开始的所有字符()、字符串-mllvm本身(注意末尾的空格)和它后面的所有字符()
- 将第三个元素(CFLAGS的其余部分落后于第一个mllvm匹配项)转换回一个带空格的字符串,并将其放入rest
- 将-mllvm标志(rest的第一个元素)的参数拉入llvm_flg
- 修改CFLAGS以包含除-mllvm及其参数之外的所有内容
- 打印变量作为调试辅助-当然要在生产中删除
- 将新找到的-mllvm标志参数追加到输出变量
- 退出声明:
- 漂亮的打印MLLVM_标志
- 从循环期间累积的CFLAG中删除空格替换字符
[[[ -DFOO§-DBAR§ -mllvm§ llvmflag1§-mllvm§llvmflag2 --- llvmflag1 -mllvm llvmflag2 --- -DFOO§-DBAR§ -mllvm llvmflag2 ]]]
[[[ -DFOO§-DBAR§§ -mllvm§ llvmflag2 --- llvmflag2 --- -DFOO§-DBAR§§ ]]]
CFLAGS = -DFOO -DBAR
MLLVM_FLAGS = llvmflag1 llvmflag2
我认为它也依赖于旗帜和它的论点之间的一个空格
$(strip)
预先设置它,以避免被过多的空格绊倒。我认为我可以安全地假设-mllvm和后续参数之间只存在一个空格(如果其他
具有子字符串-mllvm
的话,我可以添加一个断言以确定)。@Vroomfondel——只是查找strip,而且它明显地消除了单词之间的双空格。这真的很喜欢任何双间距问题。谢谢,这是一个很好的答案,但疯狂科学家的更简单。不幸的是,由于名誉的原因,我不能投票。
[[[ -DFOO§-DBAR§ -mllvm§ llvmflag1§-mllvm§llvmflag2 --- llvmflag1 -mllvm llvmflag2 --- -DFOO§-DBAR§ -mllvm llvmflag2 ]]]
[[[ -DFOO§-DBAR§§ -mllvm§ llvmflag2 --- llvmflag2 --- -DFOO§-DBAR§§ ]]]
CFLAGS = -DFOO -DBAR
MLLVM_FLAGS = llvmflag1 llvmflag2