can we undefine/unset a variable in makefile - makefile

Team,
I have an environment variable which i would like to undefined/unset during the compilation of that particular project and then enable that back..
i have tried using.. the below code..
ifdef ${ENV_VAR_TEST}
undefine ${ENV_VAR_TEST}
endif
but i still see that its get reflected in the compilation environment... are these correct steps to undefined/unset a variable ?..i am i missing some basics here..
Thanks for your time .

unexport ENV_VAR_TEST
I don't know what the others mean by undefine, which doesn't look like valid make syntax.
Edit: undefine exists indeed, but only in GNU make 3.82 and higher.

The correct syntax is
undefine ENV_VAR_TEST

You have to give the NAME of the variable to undefine. Make will expand the argument to undefine so if the variable ENV_VAR_TEST is set to the value foo, then undefine ${ENV_VAR_TEST} runs undefine foo.
You want to use undefine ENV_VAR_TEST.

Related

Is there a way to print all variables defined/visible within a makefile?

let's assume the following Makefile:
FOO=1
BAR?=test
BLAH:=$(BAR)
target:
#echo "helloworld"
Is there a way it can show me variables like this (\n or \s) ?
FOO
BAR
BLAH
bonus question:
if it is possible, is there a way to also get external variables?
make target BLABLAH=toto or export BLABLAH=toto; make target
FOO
BAR
BLAH
BLABLAH
You don't say so specifically but because of the syntax I'll assume you're using GNU make. In that case you can use the .VARIABLES special variable:
$(info Variables: $(.VARIABLES))
Note, that make target BLABLBAH=toto does not create an "external variable" (that term is not well-defined so I'm just guessing that by this you mean variables that are inherited from the environment and not set in the makefile). Setting a variable on the command line creates a real make variable and it will be shown in the list above.
Variables obtained from the environment are imported into make as makefile variables and will also appear in the above list.

Make variable that is only passed from the command line

I know that I can pass variables to a Makefile in two ways:
make <target> FOO=bar
export FOO=bar
make <target>
and that both of these will make a variable FOO available in the makefile with value bar.
However, is there a way to require that the variable only comes from the command line? I want the passing of variables to be explicit in order to avoid certain potential overlaps of environment variables, so I want to ensure make only receives the variable if passed from the command line, and to disregard it if it's only set in the environment so that the value it uses must be defined by the user when calling make.
EDIT: I realize after researching it a bit more that environment variables are not actually accessed the way I thought they are, they're actually used within make as ${FOO} so as long as I don't define FOO at any point in the makefile, its only set value will be from the command line (as noted in this answer).
These methods to pass variables to GNU make aren't equivalent.
Variables that come from the environment don't override the assignments in makefile, unless make is invoked with -e option. See variables from the environment. This is because depending on environment variables is poor practice in terms of build reproducibility (someone forgets to set the environment variable and the build is different):
It is not wise for makefiles to depend for their functioning on environment variables set up outside their control, since this would cause different users to get different results from the same makefile. This is against the whole purpose of most makefiles.
Variables that come from make command line do override assignments in makefile, unless override is specified. See the override directive.
Hence, the recommended practice is to explicitly set all your variables to their default values in the makefile unconditionally, so that only the assignments from the command line override them.
As far as I know, there's no difference between ${FOO} and $(FOO), regardless of the way FOO is defined.
If you're using GNU make, there's a function origin that allows you to make the distinction: it will return command line for a variable defined on the command line and environment for a variable exported by the environment (more info in the manual)
with the following Makefile:
foo ?= foo
default:
#echo ${foo}, comes from $(origin foo)
make prints foo, comes from file
make foo=bla prints bla, comes from command line
(export foo=bar; make) prints bar, comes from environment
expanding on #Virgile answer, you could add the following kind of check at the start of the makefile. It is a lot to repeat for each variable you wish to check, although all such checks could reside in a dedicated makefile that is then included from main makefile
foo ?= foo
# check origin
ifdef foo
ifneq "$(origin foo)" "command line"
$(error foo: must come from command line)
endif
else
$(error foo not defined)
endif
default:
#echo ${foo}, comes from $(origin foo)

How to find out the definition of the variable MAKE

Haven't been using make for a while. But just got a project from a 10 years old compiler using Ubuntu.
I am looking at the makefile and trying to find out which compiler it is using.
${MAKE} is used in the file.
But where can I find out the definition of MAKE.
Thanks
You could simply use both the info and value built-in functions inside your makefile:
$(info MAKE: $(value MAKE))
This will work if MAKE is a recursively expanded variable, which it is by default. Otherwise, if MAKE were a simply expanded variable, you will see the expansion that was done at the moment of evaluating MAKE's definition (i.e., the same as $(MAKE)).
A better approach, which is independent of the flavour of the variable, would be to run make with the option -p and look at the definition of MAKE, e.g.:
make -p | grep 'MAKE ='
You will probably find out that MAKE is defined as:
MAKE = $(MAKE_COMMAND)
and MAKE_COMMAND, which is another variable (this time, a simply expanded one), may be in turn defined as:
MAKE_COMMAND := make

Trim an environmental variable in makefile

I maintain a project which provides makefile for Arduino
There is a master (common) makefile and the users create a small makefile where they set certain environmental variables and then include the master makefile.
A typical makefile looks likes this
# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
BOARD_TAG = atmega328
ARDUINO_PORT = /dev/ttyACM*
include $(ARDMK_DIR)/arduino-mk/Arduino.mk
Recently, I was debugging a bug and then found out that if there is an additional space at the end of BOARD_TAG environmental variable, then it results in an error, which is not very intuitive for someone to fix.
My initial thought was to fix it by trimming the environmental variable inside the makefile. But on second thought I was not sure whether that is the correct way to fix this issue.
So my question is what is the recommended way to fix these kind of user input issues in makefile? Should I try to trim it or is there an alternate way to fix this?
To trim the variable "in place", just treat it as a simply expanded variable:
BOARD_TAG = atmega328
BOARD_TAG := $(strip $(BOARD_TAG))
If you use "=", it's a recursive expanded variable, so any expression on the right (e.g. $(strip ...)) will not be expanded until the variable itself is evaluated; if you try to put the variable itself on the right, Make warns you that that expression can't be evaluated because it goes into an infinite loop.
If you use ":=", it becomes a simply expanded variable; Make expands the right-hand side then and there, assigns the result to the variable and that's that.

Makefile : syntax ?=

I have a makefile from Intel in which there is some "?=".
Like
COMPILER ?= $(GCC_PATH)g++
But
EXECUTABLE = run
What is the difference between ?= and = and when do I have to use the first one instead of the second one ?
Thank you very much.
Quoth the fine documentation:
If you'd like a variable to be set to a value only if it's not already set, then you can use the shorthand operator ‘?=’ instead of ‘=’.
?= is for conditional assignment, i.e if it not already defined then only assign the value else leave it. In your example if you give make COMPILER=arm-none-gcc then arm-none-gcc is used as Compiler than the default g++, if you just type make then g++ taken as option for COMPILER. If = is used then COMPILER will be assigned value when and where assignments are encountered. for more on make files you can refer to
Understanding makefile for beginners

Resources