Dan Barowy
Dan Barowy

Reputation: 2270

Can I tell Make to ignore environment variables?

I came across some odd behavior when using Make recently (v3.81).

Suppose I have the following Makefile:

FOOBAR = $(shell find nonexistentdirectory -iname "foobar" | tr '\n' ' ')

all:
    @echo "Hi"

clean:
    @echo "Hi again"

Seems straightforward enough, right? Notably, FOOBAR is a "recursively-expanded variable", so it should not be evaluated until I refer to it. Note that I never refer to it. Also note that nonexistentdirectory does not exist as you might expect.

Now suppose I set FOOBAR in the shell before I invoke a Make target:

compy386$ FOOBAR="stuff" make clean
find: nonexistentdirectory: No such file or directory
Hi again

Why is FOOBAR being evaluated? Clearly it has something to do with the fact that the variable is defined in the shell. Am I supposed to anticipate that a user might have set variables in their shell? What am I doing wrong here?!

Upvotes: 7

Views: 2218

Answers (2)

rici
rici

Reputation: 241971

FOOBAR is being evaluated because you are running a recipe (for clean) and FOOBAR existed in the environment on entry to make. Because FOOBAR existed in the environment on entry, it becomes an exported variable, which means that make will provide it as part of the environment to any program in the recipe. make doesn't special-case echo; it just uses the one found in your path. And it can't know whether or not that utility will reference a particular environment variable, so it has to export all exported variables, which means it has to evaluate FOOBAR.

(For the official word, see the third paragraph of Variables from the Environment in the make manual. Also see the recipe on recursive make invocation.)

To answer the direct question, you can tell make to ignore the fact that a variable came from the environment, so that it doesn't re-export it, by unexporting it:

unexport FOOBAR

Upvotes: 3

cforbish
cforbish

Reputation: 8829

Add a ? before the = like:

FOOBAR ?= $(shell find nonexistentdirectory -iname "foobar" | tr '\n' ' ')

This will use the environment variable if set and only evaluate if unset or empty.

Upvotes: 0

Related Questions