Ian Storm Taylor
Ian Storm Taylor

Reputation: 8680

Require an environment variable to be set in a Makefile target

I'm trying to require that an environment variable be set in a Makefile when running a specific target. I'm using the technique from the answer to this question, where you setup another target that will guarantee an environment variable to be set.

Mine looks like this:

require-%:
    @ if [ "${${*}}" = "" ]; then \
        $(error You must pass the $* environment variable); \
    fi

With that target setup, this is expected:

$ make require-FOO
Makefile:3: *** You must pass the FOO environment variable.  Stop.

However, when testing, I can never get it to not error:

$ make require-FOO FOO=something
Makefile:3: *** You must pass the FOO environment variable.  Stop.

$ make require-FOO FOO=true
Makefile:3: *** You must pass the FOO environment variable.  Stop.

$ make require-FOO FOO='a string'
Makefile:3: *** You must pass the FOO environment variable.  Stop.

Even when I comment out the if block in the target:

require-%:
    # @ if [ "${${*}}" = "" ]; then \
    #   $(error You must pass the $* environment variable); \
    # fi

I still get an error when running it:

$ make require-FOO FOO=something
Makefile:3: *** You must pass the FOO environment variable.  Stop.

What's am I doing wrong? How can I get this to work?

Upvotes: 1

Views: 1588

Answers (1)

Etan Reisner
Etan Reisner

Reputation: 80921

You modified the solution presented in that linked answer without understanding the difference.

The linked answer uses a shell echo and a shell exit to do the message output and exiting.

Your modification uses the make $(error) function.

The difference is that the shell commands only execute when the shell logic says they should but the make function executes before make runs the shell commands at all (and always expands/executes). (Even in shell comments because those are shell comments.)

If you want this asserted at shell time then you need to use shell constructs to test and exit. Like the original answer.

If you want this asserted at recipe expansion time then you need to use make constructs to test and exit. Like this (untested):

require-%:
    @: $(if ${${*}},,$(error You must pass the $* environment variable))
    @echo 'Had the variable (in make).'

Upvotes: 7

Related Questions