[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: exported vs command line variables

From: David Boyce
Subject: Re: exported vs command line variables
Date: Fri, 23 Sep 2016 05:52:59 -0700

Changing the subject a bit, I was unpleasantly surprised to learn while following this discussion that "Except by explicit request, make exports a variable only if it is either defined in the environment initially _or set on the command line_". For years I've noticed a tendency for users to mark variables for export indiscriminately in order to get them to some child make. Sort of a "big hammer" approach, which I dislike for the same reason global variables etc are deprecated: once every child process (not just every child make) can see a variable, there's no way to know who depends on it and the result is both harder to debug and harder to clean up. I generally advise people that rather than:

export CFLAGS
$(MAKE) -C subdir ...

They should pass required variables on the command line:

$(MAKE) -C subdir CFLAGS="$(CFLAGS)"

to keep scoping under control. I still think that's a good plan, except that now I find out it ends up exporting anyway. I'm sure it's too late to change now but is there a reason for this (unfortunate IMHO) behavior?

The only workaround I can think of would be to rely on non-alphanumeric names like $(C-FLAGS) but that's a long way from elegant or obvious.


On Tue, Sep 20, 2016 at 11:24 AM, Paul Smith <address@hidden> wrote:
On Tue, 2016-09-20 at 15:28 +0000, Pietro wrote:
> Hi,
> I have noticed that there is a difference between the two scenarios
> listed below:
> i) make  CC=arm-linux-gnueabihf-gcc CPPFLAGS=[..]
> ii) export CPPFLAGS=[..] [RET]
>     make CC=arm-linux-gnueabihf-gcc
> I was told that the difference is that in the second case Make
> will append stuff to the CPPFLAGS variable exported while in the
> first case the command line argument will override the settings
> contained in the makefile itself.

That is definitely not true.  Whether or not the values here replace or
append to any value of CPPFLAGS in the makefile depends entirely on how
the variable is set in the makefile.

GNU make has a hierarchy of precedence when it comes to how variables
are set.  The weakest setting is values that are built-in to make.
 Next highest is values taken from the environment.  Those are
overridden by values set in the makefile itself.  And finally values
set on the command line have the highest precedence.

So if you have a makefile like this:

  CPPFLAGS = -Wall

  all: ; echo 'CPPFLAGS=$(CPPFLAGS)'

Then if you run:

  $ CPPFLAGS=-Werror make

and the makefile setting overrides the environment setting.  But:

  $ make CPPFLAGS=-Werror

command line settings take precedence over makefile settings.  In
neither case will the value in the environment or command line be
appended to the value in the makefile: it always replaces the value.

There are ways you can manipulate the priority, using the -e command
line option and the override specifier on variable assignment (see the
GNU make manual for this).  

> The following example, literally pasted from another thread could
> clarify the matter :
> var := $(shell echo "echo hi" >say_hi.sh; chmod +x say_hi.sh;
> say_hi.sh)
> all: ; @echo $(var)

This actually just adds a lot of confusion and doesn't clarify it at
all, because (a) you're using PATH environment variable here which is
"special", at least nominally and (b) you're using $(shell ...) not
recipes, and the behavior of the shell function with respect to the
environment is different from that of recipes.  This example seems to
me to be completely different than what you asked about above, such
that you can't really compare them.

> I have posted a question at the general make mailing list and I was
> told that this might be a bug, I would love to have a clarification -
> is it a bug ?

I think this is more a matter of you wanted to do something and you
followed a path and got stuck, so you asked about what got you stuck.

I think you should back up and ask about what you are really trying to
do in the first place, with an example, because likely the path you
followed is not the one you want so discussing where you're stuck won't
really help.

Bug-make mailing list

reply via email to

[Prev in Thread] Current Thread [Next in Thread]