It's common to have options in a Makefile that you alter when you start a build. Perhaps the most common is a DEBUG option used to specify whether the build you are doing creates debuggable or release code.
A simple way to handle this is with a Makefile variable called BUILD_DEBUG which is set to yes in the Makefile and overriden on the GNU Make command-line when building the release version. In that case you might see something like
at the start of the Makefile. That sets the default to be debug builds and is overriden by doing
when it's release time. And around release time you might be tempted to define BUILD_DEBUG to be no in your shell's start up script (e.g. in .cshrc or .bashrc) so that all your builds are release. Unfortunately, this doesn't work. To see why you need to understand how GNU Make sets variables in a Makefile. Start by considering this simple Makefile that prints the value of BUILD_DEBUG:
BUILD_DEBUG=yes all: ; @echo BUILD_DEBUG is $(BUILD_DEBUG)
Trying three runs of the Makefile (once with no options, once setting BUILD_DEBUG on GNU Make's command-line and finally with BUILD_DEBUG set in the environment) yields:
$ gmake BUILD_DEBUG is yes $ gmake BUILD_DEBUG=no BUILD_DEBUG is no $ export BUILD_DEBUG=no $ gmake BUILD_DEBUG is yes
The last line shows that variables defined inside a Makefile override values in the environment. If you want to us a hammer to “solve” this problem you can set GNU Make's -e switch which makes the environment take precedence, but that affects every variable not just the one we are concerned with.
The rule to remember is (like the old paper, scissors, rock game): command-line beats Makefile beats environment. So a variable defined on the command-line will take precedence over the same variable defined in a Makefile which will take precedence over the same variable defined in the environment.
So suppose you want to have a BUILD_DEBUG variable that is set by default to yes and can be overriden either on the command-line or in the environment. GNU Make provides two ways to achieve that. Both rely on checking to see if the variable is already defined.
Here's one way. Replace the setting of BUILD_DEBUG in the original Makefile to
ifndefBUILD_DEBUG BUILD_DEBUG=yes endif
Now if BUILD_DEBUG has not already been set (that's what ndef means: not defined) then it will be set to yes, otherwise it is left unchanged. Since that's a bit of a mouthful GNU Make provides a shorthand for the pattern ifndef/set variable/endif in the form of the ?= operator. With a one character change we get the desired result:
BUILD_DEBUG?=yes all: ; @echoBUILD_DEBUG is $(BUILD_DEBUG)
The ?= says set BUILD_DEBUG to yes, unless it is already defined, in which case leave it alone. Rerunning the test from above reveals:
$ gmake BUILD_DEBUG is yes $ gmake BUILD_DEBUG=no BUILD_DEBUG is no $ export BUILD_DEBUG=no $ gmake BUILD_DEBUG is no
And this provides the ultimate flexibility allowing a default setting in the Makefile which is overriden in the environment and a temporary override on the command-line.
$ export BUILD_DEBUG=no $ gmake BUILD_DEBUG=aardvark BUILD_DEBUG is aardvark