编写构建Docker镜像的Makefile报prerequisites cannot be defined in recipes错求助
错误原因
eval函数的作用是动态生成Make规则,这类规则定义逻辑必须放在Makefile的顶层解析阶段执行,不能放在任意目标的recipe(目标冒号后缩进的执行命令块)中。- Make运行时会先完成所有顶层规则、目标、依赖的解析,再执行选中目标的脚本命令。你现在把生成
build_xxx规则的代码放在build目标的脚本段里,等于在命令执行阶段才尝试定义依赖关系,直接违反了Make的执行逻辑,因此触发报错。
修复方法
把动态生成规则的foreach逻辑从目标的recipe中移出,放在Makefile顶层,不需要缩进,也不归属任何目标。修正后的完整代码如下:
# 假设每个子目录都包含一个Dockerfile IMAGES := $(patsubst %/,%,$(dir $(wildcard */Dockerfile))) BUILD_TARGS = $(patsubst %,build_%,$(IMAGES)) TEST_TARGS = $(patsubst %,test_%,$(IMAGES)) PUSH_TARGS = $(patsubst %,push_%,$(IMAGES)) VERSION := 1 # 可替换为 git 命令取版本号:$(shell git rev-parse --short=12 --verify HEAD) DOCKER_REPO_URL := david.io/reponame define docker_build = build_$(1): @echo "Building $(1)" #docker build -t $(1) --force-rm $(1) endef define docker_test = test_$(1): @echo "Testing $(1)" #docker inspect $(1) #docker run --rm $(1) help endef define docker_push = push_$(1): @echo "Pushing $(1)" #docker tag $(1) $(DOCKER_REPO_URL):$(1)-$(VERSION) #docker push $(DOCKER_REPO_URL):$(1)-$(VERSION) #docker tag $(1) $(DOCKER_REPO_URL):$(1) #docker push $(DOCKER_REPO_URL):$(1) endef # 动态生成所有规则,放在顶层解析段 $(foreach image,$(IMAGES),$(eval $(call docker_build,$(image)))) $(foreach image,$(IMAGES),$(eval $(call docker_test,$(image)))) $(foreach image,$(IMAGES),$(eval $(call docker_push,$(image)))) .PHONY: all build test release clean $(IMAGES) $(BUILD_TARGS) $(TEST_TARGS) $(PUSH_TARGS) all: build test release build: $(BUILD_TARGS) test: $(TEST_TARGS) release: $(PUSH_TARGS)
内容的提问来源于stack exchange,提问作者david
相关产品推荐
相关产品推荐

