无论文件是否存在,都使用变量名运行目标

Make runs target with variable name regardless of whether file exists

我正在使用 GNU make 处理一些数据。当我尝试 运行 具有变量名的目标时,make 将 运行 该目标, 不管目标文件是否已经存在 。考虑以下 Makefile

include config.mk

.PHONY : all
all : $(PG_DB).db

$(PG_DB).db : 
    createdb $(PG_DB) -U $(PG_USER)
    touch $@

其中 config.mk 包含:

MAKEFLAGS += --warn-undefined-variables
SHELL := bash
.SHELLFLAGS := -eu -o pipefail
.DEFAULT_GOAL := all
.DELETE_ON_ERROR:
.SUFFIXES:

PG_USER="foo"
PG_DB="foo"

当我 运行 make 时,make 创建 Postgres 数据库,然后访问文件 foo.db。但是,当我再次 运行 make 时,输出是:

createdb "foo" -U foo
createdb: database creation failed: ERROR: database "foo" already exists
make : *** ["foo".db] Error 1

这不应该发生!我希望 make,在这种情况下,检查假目标 all 的先决条件,看到 foo.db 已经存在,然后立即退出而不做任何事情。

奇怪的是,这正是我删除目标名称中的变量时发生的情况:

include config.mk

.PHONY : all
all : foo.db

foo.db :
    createdb $(PG_DB) -U $(PG_USER)
    touch $@

当我 运行 make 修改 Makefile 时,我得到:

make: Nothing to be done for `all`.

这正是我所期望的。

这是怎么回事?

问题不是出在变量上,而是出在变量值中的引号上。 make 检查依赖关系前不去掉引号。因此它正在检查包含引号的文件 "foo".db。命令 touch "foo".db 被删除引号的 shell 解释。所以对于 make,该文件将永远不会存在,您将始终遇到同样的问题。当您显式放置依赖项时,您将其放置为不包含引号的 foo.db 。它让一切变得不同。

在config.mk,转

PG_DB="foo"

进入

PG_DB=foo

应该可以。我想 createdb 是一个普通的 shell 命令,不会在意引号。否则你需要在调用命令之前添加它。