代码管理:生成具有各种规则细微变化的源文件

code management: generate source files with slight variations of various rules

我有一个声明性语言的源文件(twolc,实际上)我需要写很多变体:一个规范版本和许多非规范版本,每个版本都有一个或多个变体规范。例如,假设规范文件具有三个规则:

Rule A:
    Do something A-ish

Rule B:
    Do something B-ish

Rule C:
    Do something C-ish

那么一个变体可能与 AC 的规范具有完全相同的规则,但 B 的规则不同,我将其称为 B-1 :

Rule A:
    Do something A-ish

Rule B-1:
    Do something B-ish, but with a flourish

Rule C:
    Do something C-ish

假设您对许多不同的规则有许多不同的细微变化,并且您有我的情况。我担心的问题是代码的可维护性。如果稍后我决定 Rule A 需要以某种方式重构,那么我将有 50 多个文件需要手动编辑完全相同的规则。

我的想法是为每个规则创建单独的文件,并使用 cat 将它们连接成变体:cat A.twolc B.twolc C.twolc > norm.twolccat A.twolc B-1.twolc C.twolc > not-norm.twolc

是否有专为解决此类问题而设计的工具?有没有比我想到的更好的方法?我提出的解决方案是否有我应该注意的弱点?

当您添加 makefile 标签时,这里是一个基于 GNU-make(且仅 Gnu make)的解决方案:

# Edit this
RULES       := A B B-1 C
VARIATIONS  := norm not-norm
norm-rules  := A B C
not-norm-rules  := A B-1 C
# Do not edit below this line

VARIATIONSTWOLC := $(patsubst %,%.twolc,$(VARIATIONS))

all: $(VARIATIONSTWOLC)

define GEN_rules
$(1).twolc: $$(patsubst %,%.twolc,$$($(1)-rules))
    cat $$^ > $$@
endef
$(foreach v,$(VARIATIONS),$(eval $(call GEN_rules,$(v))))

clean:
    rm -f $(VARIATIONSTWOLC)

patsubst 很简单。 foreach-eval-call 有点棘手。长话短说:它遍历所有变体 (foreach)。对于每个变体 v,它通过将 $(1) 替换为 $(v)(当前变体)并将 $$ 替换为 [= 来扩展 (call) GEN_rules 24=]。然后将每个扩展结果实例化 (eval) 作为正常的 make 规则。示例:对于 v=normGEN_rules 扩展产生:

norm.twolc: $(patsubst %,%.twolc,$(norm-rules))
    cat $^ > $@

依次展开为(逐步):

第一步:

norm.twolc: $(patsubst %,%.twolc,A B C)
    cat $^ > $@

第 2 步:

norm.twolc: A.twolc B.twolc C.twolc
    cat $^ > $@

第 3 步:

norm.twolc: A.twolc B.twolc C.twolc
    cat A.twolc B.twolc C.twolc > norm.twolc

做你想做的事:如果 norm.twolc 不存在或者 A.twolcB.twolcC.twolc 中的任何一个比 norm.twolc 更新, 配方被执行。