【问题标题】:Make runs target with variable name regardless of whether file exists无论文件是否存在,都使用变量名运行目标
【发布时间】:2015-07-21 18:37:12
【问题描述】:

我正在使用 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 $@

当我使用修改后的Makefile 运行make 时,我得到:

make: Nothing to be done for `all`.

这正是我所期望的。

这是怎么回事?

【问题讨论】:

  • 在变量失败案例中包含运行make -rRd 的输出?还有这是什么版本的make? 4.0? 4.1?

标签: makefile gnu-make


【解决方案1】:

问题不是来自变量,而是来自变量值中的引号。 make 在检查依赖关系之前不会删除引号。因此它正在检查包含引号的文件"foo".db。虽然命令 touch "foo".db 由删除引号的 shell 解释。所以对于make,文件永远不会存在,你总是会遇到同样的问题。当您明确放置依赖项时,您将其放置为不包含引号的foo.db。它使一切变得不同。

在config.mk中,转

PG_DB="foo"

进入

PG_DB=foo

它应该工作。我猜 createdb 是一个普通的 shell 命令,不会关心引号。否则,您需要在调用命令之前添加它。

【讨论】:

  • 谢谢!就是这样。我没有意识到 Makefile 中值的引号总是被解释为文字。
猜你喜欢
  • 1970-01-01
  • 2014-02-08
  • 2015-04-14
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 2012-09-28
相关资源
最近更新 更多