首页 > 解决方案 > Makefile:将 PHONY 目标声明为配方先决条件

问题描述

我的 Makefile 正在捆绑配方以并行处理大量文件(make <recipe> -j8等)。但在处理文件之前,需要使用find. 这是一个耗时的操作,所以我只想为用户调用的确切配方运行它。我可以这样做:

test: FILES=$(shell find "$(SEARCHDIR)/" -mindepth 3 -maxdepth 3 -type f ! -regex $(SOMEREGEX))
test: $(FILES)
$(FILES):
    echo "do thing with file $@ here"

问题在于,由于文件本身已经存在,因此需要将它们声明为.PHONY才能运行配方,如下所示:

.PHONY: $(FILES)

但是为了使它起作用,FILES变量需要存在并被填充,这需要我运行find命令。这违背了我不执行搜索以查找FILES直到test被调用的目标。我需要的是这样的:

test: FILES=$(shell find "$(SEARCHDIR)/" -mindepth 3 -maxdepth 3 -type f ! -regex $(SOMEREGEX))
test: .PHONY: $(FILES)
test: $(FILES)
$(FILES):
    echo "do thing with file $@ here"

但是test: .PHONY: $(FILES)是无效的语法并且不起作用。

标签: makefile

解决方案


.PHONY即使没有这个东西,你的 makefile 也已经不起作用了;只是:

test: FILES=$(shell find "$(SEARCHDIR)/" -mindepth 3 -maxdepth 3 -type f ! -regex $(SOMEREGEX))

$(FILES):
        echo "do thing with file $@ here"

失败是因为$(FILES)make解析生成文件时,规则的目标在开始运行test目标之前扩展为空字符串。

我建议你在这里使用递归 make;像这样写你的makefile:

FIND_FILES :=
FILES :=
ifneq ($(FIND_FILES),)
FILES := $(shell find "$(SEARCHDIR)/" -mindepth 3 -maxdepth 3 -type f ! -regex $(SOMEREGEX))
endif

test:
        $(MAKE) test-recurse FIND_FILES=1

test-recurse: $(FILES)
$(FILES):
        echo "do thing with file $@ here"
.PHONY: test test-recurse $(FILES)

推荐阅读