makefile目标中的条件变量赋值



我试图在makefile目标中获得条件赋值,前提是它不是由要求的目标设置的:

REPO_PROD = prod
REPO_DEV = dev
.PHONY: ko-build-container
ko-build-container: KO_DOCKER_REPO ?= $(REPO_PROD)
ko-build-container:
@echo $(KO_DOCKER_REPO)
.PHONY: ko-build-container-dev
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container

不幸的是,make ko-build-container-dev打印prod。我在这里错过了什么?

另一种选择是使用第三个目标,如:

ko-build-container-base:
echo $(KO_DOCKER_REPO)
ko-build-container: KO_DOCKER_REPO = $(REPO_PROD)
ko-build-container: ko-build-container-base
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container-base

显然,在GNU make中,条件赋值(赋值或不赋值(的结果是在只有全局变量可用的阶段决定的,但最终值的选择来自于继承的目标特定变量也可用的后期阶段。因此,更奇怪的是,在因为设置了全局变量而跳过条件赋值后,最终值不一定是全局变量的值,它可以从父目标继承!演示:

$ cat Makefile
.PHONY: sub all
all: VAR = all
all: sub
# no global VAR set => assign instead of using inherited VAR = all
sub: VAR ?= sub
sub:
@echo $(VAR)
$ make
sub
$ cat Makefile
.PHONY: all
VAR = global
# global VAR set => do not assign, use global VAR = global
all: VAR ?= all
all:
@echo $(VAR)
$ make
global
$ cat Makefile
.PHONY: sub all
VAR = global
all: VAR = all
all: sub
# global VAR set => do not assign... but use inherited VAR = all
sub: VAR ?= sub
sub:
@echo $(VAR)
$ make
all

这里报道了这种奇怪的行为:https://savannah.gnu.org/bugs/?18305此外,还讨论了是否应该/可以对其进行修复。

我认为,在条件赋值中,将结果与值的选择分离显然是一个错误。没有人会想到这样奇怪的行为。无论如何,您可以使用讨论中建议的变通方法:,而不是特定于目标的条件分配

$ cat Makefile
REPO_PROD = prod
REPO_DEV = dev
.PHONY: ko-build-container
ko-build-container:
@echo $(or $(KO_DOCKER_REPO),$(REPO_PROD))
.PHONY: ko-build-container-dev
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container
$ make ko-build-container-dev
dev

最新更新