匹配Makefile目标的不同/多个部分

时间:2016-12-16 09:02:59

标签: makefile pattern-matching target

这是一个Makefile,我目前用它来制作具有不同配置的目标,即我正在构建具有相同目标的不同软件包,无论是一次还是单独创建。

.PHONY: build test %.build %.test build-all test-all
%.build %.test: PACKAGE = $*

%.build:
    @echo build $(PACKAGE)

%.test:
    @echo test $(PACKAGE)

build-all: a.build b.build
test-all:  a.test  b.test

build: $(PACKAGE).build
test:  $(PACKAGE).test

我现在可以使用make build-all或单个包构建所有包,例如make build PACKAGE=a。但是,我想切换%.buildbuild等目标的正文,如下所示:

.PHONY: build test %.build %.test build-all test-all
build:
    @echo build $(PACKAGE)

test:
    @echo test $(PACKAGE)

build-all: a.build b.build
test-all:  a.test  b.test

%.build %.test: PACKAGE = $*
$(PACKAGE).%: $*

这样,模式匹配逻辑与" main"完全分离。应包含实际构建命令的目标buildtest;使Makefile的重要部分更具可读性。但是,最后一行不能按预期工作,即运行make a.build,因此make build-all应使用build触发目标PACKAGE=a。在倒数第二行中的变量赋值起作用,最后一行中的目标匹配不起作用。

问题:有没有办法表达匹配的目标,例如$(PACKAGE).%: $*或匹配目标的不同部分,例如%.%: $2

2 个答案:

答案 0 :(得分:0)

首先你可能想要:

$(PACKAGE).% : %

不使用$*,这是一个自动变量,所以除了食谱之外它没有任何价值;你不能像在先决条件清单中那样使用它。

其次,你不能在GNU make中这样做。没有配方的模式规则不仅仅是创建先决条件关系,就像显式规则一样;而是删除模式规则。由于您还没有$(PACKAGE).%的模式规则,这基本上是一个无操作。此外,特定于目标的变量仅在配方中可用,因此尝试在目标定义中使用$(PACKAGE)并期望它从某些先前设置的特定于目标的变量中获取值不起作用。

你可以这样做,但它不是完全动态的(你仍然需要包和类型列表):

PACKAGES = a b
TYPES = build test

$(foreach T,$(TYPES),$(eval $(addsuffix .$T,$(PACKAGES)): $T))

答案 1 :(得分:0)

正如MadScientist所解释的那样,这个问题在GNU make中无法轻易解决。为了完整起见,我想补充并解释我的最终和更全面的解决方案:

.PHONY: all build test clean %.build %.test build-all test-all

PACKAGES  = a b c e f g
PACKAGE   = a

all: clean build-all test-all

%.build %.test: PACKAGE = $*

%.build:
    @echo build $(PACKAGE)

%.test:
    @echo test $(PACKAGE)

clean:
    @echo remove build dir

build-all: $(addsuffix .build, $(PACKAGES))
test-all:  $(addsuffix .test,  $(PACKAGES))

build: $(PACKAGE).build
test:  $(PACKAGE).test

此解决方案避免使用evalforeach,并且基于我的初始工作解决方案,其中动态%.build%.test目标包含实际的构建命令。我添加了PACKAGES变量以便于添加新软件包,默认PACKAGE以防止执行错误配置的构建命令,并添加公共目标allclean作为补充。

在命令行中,您只需拨打make allcleanbuild PACKAGE=xbuild-all等,即只有静态目标,然后,它将触发动态目标中的构建命令。静态目标和两个变量在Bash / Zsh自动完成中也可见。

我认为这是构建多个动态目标的最灵活且可读的方式。