Justin Manley
Justin Manley

Reputation: 258

Make runs target with variable name regardless of whether file exists

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

Answers (1)

innoSPG
innoSPG

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

Related Questions