I have several environment variables set in my makefile that all have a common prefix, and others that do not share the prefix. How can I grab all of the variables that do have that prefix, and prepend a -D to the front of it, and set those all to a new variable? See below:
ENVIRONMENT VARIABLES
=====================
FOOD_VEGETABLE
FOOD_FRUIT
FOOD_DESSERT
HEAT
GAS
So I want a new variable FOOD_FEATURES to grab all of the FOOD_* variables, and prepend a -D prefix. If I printed FOOD_FEATURES I would get this:
$(warning $(FOOD_FEATURES))
gives
-DFOOD_VEGETABLE -DFOOD_FRUIT -DFOOD_DESSERT
If you have a sufficiently new version of GNU make, you can use the .VARIABLES special variable for this sort of introspection:
FOOD_FEATURES := $(patsubst %,-D%,$(filter FOO_%,$(.VARIABLES)))
I should point out that this will match all make variables containing the prefix FOO_, not just environment variables. If you really want only environment variables that's doable, but much more complex; something like:
FOOD_FEATURES := $(patsubst %,-D%,$(foreach V,$(filter FOO_%,$(.VARIABLES)),$(if $(filter environment,$(origin $V)),$V)))
Related
When I run
export PATH := mypath
$(error $(shell echo "$${PATH}"))
it seems my PATH isn't changed on the call to shell.
Why is this and how do I actually change the PATH for shell calls?
Is this with GNU make? There is a long-standing GNU make feature request to honor exported variables with $(shell …). This is not specific to PATH at all, it affects (or does not affect) all export variables.
According to the GNU make sources, this is tricky to implement:
/* Using a target environment for 'shell' loses in cases like:
export var = $(shell echo foobie)
bad := $(var)
because target_environment hits a loop trying to expand $(var) to put it
in the environment. This is even more confusing when 'var' was not
explicitly exported, but just appeared in the calling environment.
See Savannah bug #10593.
envp = target_environment (NULL);
*/
The solution is simple: never ever use $(shell) or export.
Environment variables should be part of the recipe that needs them.
For $(shell) invocations that are supposed to fill a makefile variable you can use instead.
it also has the advantage to be more flexible, because you can fill more than one variable with one recipe
you can also define proper dependencies, whereas $(shell) is always executed, either when the makefile is parsed or the recursively expanded variable gets expanded.
you get build errors and recipes are logged, whereas $(shell) can make the DevOp engineers life a living h...
PATH := mypath
Makefile.variables:
#PATH=$(PATH) echo "This my path '$${PATH}'"
echo >$# "MY_DYNAMIC_CONTENT := abcd"
include Makefile.variables
$(info MY_DYNAMIC_CONTENT '$(MY_DYNAMIC_CONTENT)')
Example run:
$ make
MY_DYNAMIC_CONTENT ''
This my path 'mypath'
echo >Makefile.variables "MY_DYNAMIC_CONTENT := abcd"
MY_DYNAMIC_CONTENT 'abcd'
make: 'Makefile.variables' is up to date.
From within a GNU makefile, is there a way to take all variables with a given prefix, and pass them as -D defines to a compile command?
For example, given that following variables exist:
DEFINE_FOO=cat
DEFINE_BAR=dog
Is there a way to automatically generate the string -DFOO=cat -DBAR=dog from within make such that it automatically picks up any variables added later with the prefix DEFINE_?
If you use GNU make, you can do it like this:
CPPFLAGS += $(patsubst DEFINE_%,-D%,$(foreach V,\
$(filter DEFINE_%,$(.VARIABLES)),$V=$($V)))
In my makefile I have a variable FOO:
FOO = /path/to/bar
Is it possible to overwrite this variable during the makefile call? Somthing like the following:
FOO=/path/to/foo make all
Specify them as Var=Value before you specify the target, like make FOO=/path/to/foo all.
$ cat Makefile
Foo = asdf
all:
echo $(Foo)
$ make all
echo asdf
asdf
$ make Foo=bar all
echo bar
bar
The ways that variables get assigned values is specified in the How Variables Get Their Values section of the GNU make Manual.
Variables can get values in several different ways:
You can specify an overriding value when you run make. See Overriding Variables.
You can specify a value in the makefile, either with an assignment (see Setting Variables) or with a verbatim definition (see Defining Multi-Line Variables).
Variables in the environment become make variables. See Variables from the Environment.
Several automatic variables are given new values for each rule. Each of these has a single conventional use. See Automatic Variables.
Several variables have constant initial values. See Variables Used by Implicit Rules.
So, as Colonel Thirty Two indicates, you can override variables set in the makefile on the command line.
You can also, if you expect this to be a variable that you want to set persistently, use the ?= assignment and then environment values for that variable will be used.
I try to implement a non-recursive make build system in my current project. What I struggle with is variables scopes. Target specific variables don't fit my needs as often variables define targets and not prerequisites.
What I need is:
Makefile1:
SOMEVAR := original_value
include Makefile2
$(warning $(SOMEVAR))
Makefile2:
#some magic here to do what I want and make me happy
SOMEVAR := included_value
#and maybe here
And the output I want is 'original_value'.
Are there any strategies to make it real?
EDIT: The only solution I came for the moment is to force and organize myself to place all inlcudes in the end of each particular Makefile and use immediate variable assignment :=
One strategy is the old-fashioned solution to variable name collisions when all you have is global variables: add a prefix to your variable names in a form of poor-man's namespaces.
Makefile1:
Makefile1_SOMEVAR := original_value
include Makefile2
$(warning $(Makefile1_SOMEVAR))
Makefile2:
# no magic needed
Makefile2_SOMEVAR := included_value
# rest of Makefile2 uses $(Makefile2_SOMEVAR) of course
Hey presto, with a convention like this it's as if each makefile has its own local variables (or, at least, its own variables in a namespace that doesn't collide with any other makefiles).
I want to do immediate expansion of a shell command within a Makefile, but I want the shell command to have access to the environment variables within the Makefile. If I use the $(shell ...), it expands immediately, but there is no access to the variables. If I use the backquotes, the expansion is not immediate, and it causes problems for me later in the Makefile. I'm wondering if there is any way to make the backquotes expand immediately, or to pass the current environment to a $(shell) command.
For example, the following makefile:
SOME_VAR := some_val
export SOME_VAR
VAR1 := `echo $$SOME_VAR`
export VAR1
VAR2 := `echo $$VAR1`
all:
#echo VAR1=$(VAR1)
#echo VAR2=$(VAR2)
Will output:
~/tmp/t2> make
VAR1=some_val
VAR2=`echo $SOME_VAR`
Where I want it to print "VAR2=some_val". The real example is a bit more complicated (environment variables are inherited from parent makefiles, and I'm trying to use a perl script to edit the variables), but the principle is the same.
Any help is appreciated.
Is this what you want?
VAR2 := $(shell VAR1="$(VAR1)" script_that_uses_var1)
What's wrong with this?
VAR1 := $(shell echo $(SOME_VAR))
VAR2 := $(shell echo $(VAR1))
You may try to use Special Built-in Target Name: .EXPORT_ALL_VARIABLES
.EXPORT_ALL_VARIABLES:
MY_VAR = foo
test:
#echo $$MY_VAR
As I mentioned in some of the comments, my actual goal was to make the script generate filenames based on the settings the object was being compiled with. I then need another script to generate a specially formatted list of all the filenames generated (the target is an embedded system which doesn't have a JIT compiler on it). At any given time, there are over thirty settings which can potentially effect the binary, and this may be used on more than one module in the future, so I'd like something scalable.
My solution is as follows. Instead of passing the variables in, I modified my script to output a makefile-parsable string based on the settings:
-include $(SOME_MK_FILE)
$(SOME_MK_FILE) : .phony
script.pl $(SETTINGS_OF_INTEREST_LIST) > $(SOME_MK_FILE)
someFilename := $(shell script2.pl $(VAR1))
script.pl outputs a string that looks something like:
VAR1 := CONFIG_X1=$(CONFIG_X1) CONFIG_X2=$(CONFIG_X2) CONFIG_X33=$(CONFIG_X33)
and script2 outputs a filename that looks something like 'someFilename.X1_y.X2_n.elf'
and then, later on, in another rule, I have:
someobj: somedep
script3.pl $(someFilename) >> builtfiles.txt
which properly builds builtfiles.txt (which in turn is the input for yet another script...). In the end this is a workaround to the fact that make cannot pass its environement to $(shell). It's not overly pretty but it works.
John
Here you go:
export FOO=bar
Here's a page with a lot more info:
http://www.cmcrossroads.com/article/basics-getting-environment-variables-gnu-make?page=0%2C1