Reputation: 258
I'm using GNU make to work with some data. When I try to run a target with a variable name, make will run that target, regardless of whether the target file already exists. Consider the following Makefile
:
include config.mk
.PHONY : all
all : $(PG_DB).db
$(PG_DB).db :
createdb $(PG_DB) -U $(PG_USER)
touch $@
where config.mk contains:
MAKEFLAGS += --warn-undefined-variables
SHELL := bash
.SHELLFLAGS := -eu -o pipefail
.DEFAULT_GOAL := all
.DELETE_ON_ERROR:
.SUFFIXES:
PG_USER="foo"
PG_DB="foo"
When I run make
, make creates the Postgres database, and then touches the file foo.db
. However, when I run make
again, the output is:
createdb "foo" -U foo
createdb: database creation failed: ERROR: database "foo" already exists
make : *** ["foo".db] Error 1
This shouldn't have happened! I would expect make
, in this situation, to check the prerequisites for the phony target all
, see that foo.db
already exists, and exit immediately without doing anything.
Strangely, this is exactly what happens when I get rid of the variables in the target names:
include config.mk
.PHONY : all
all : foo.db
foo.db :
createdb $(PG_DB) -U $(PG_USER)
touch $@
When I run make
with this modified Makefile
, I get:
make: Nothing to be done for `all`.
Which is exactly what I expect.
What's going on here?
Upvotes: 2
Views: 355
Reputation: 4656
The problem does not come from the variable, it comes from the quotation mark in the variable value. make
does not remove the quotation mark before checking the dependency. So it is checking for the file "foo".db
with the quotation mark included. While the command touch "foo".db
gets interpreted by the shell
that removes the quotation marks. So for make
, the file will never be there and you will always have the same problem. When you put the dependency explicitly, you put it as foo.db
that does not include the quotation mark. It makes all the difference.
in config.mk, turn
PG_DB="foo"
into
PG_DB=foo
it should work. I guess createdb is a normal shell command that will not care about the quotation marks. Otherwise you will need to add it before calling the command.
Upvotes: 1