I have the following Makefile:
all: print1 print2
world=world1
print1:
#echo $(world)
world=world2
print2:
#echo $(world)
.PHONY: all print1 print2
When running with make I expected to get:
world1
world2
But I got:
world2
world2
Is it possible to get the expected output only with the variable world?
Target-specific variable values were made for this.
print1: world=world1
print1:
#echo $(world)
print2: world=world2
print2:
#echo $(world)
And if the recipes are identical, you can combine the rules:
print1: world=world1
print2: world=world2
print1 print2:
#echo $(world)
Related
Is it possible to pass value with single dollar from shell to Makefile, or I it is only way to put double dollar in bash and then to call make?
Makefile is:
HASH ?= $$6$$salt$$val
.PHONY: tst
tst:
echo '$(HASH)'
Command to run:
> make HASH='$6$salt$val'
echo 'altal'
altal
If I use double quotes, all is fine:
> make HASH='$$6$$salt$$val'
echo '$6$salt$val'
$6$salt$val
But is it possible do not make substitution $ to $$ in bash?
How about writing the initialisation within the file identical to the one coming from the command line? The below script demonstrates how to rewrite a variable with the override directive:
quote-one-level = $(eval override $1=$(subst $,$$$$,$(value $1)))
var-info = $(info $1=$(value $1) flavour=$(flavor $1) origin=$(origin $1))
A ?= $abc
$(call var-info,A)
$(call quote-one-level,A)
$(call var-info,A)
$(call var-info,B)
$(call quote-one-level,B)
$(call var-info,B)
export A
export B
all:
#echo A = '$(A)'
#echo B = '$(B)'
ifeq ($(MAKELEVEL),0)
$(MAKE)
endif
Inflating one $ to $$$$ (and not just $$) is necessary because the eval command literally generates make code, thereby obviously reducing the quoting level by one. Resulting output:
$ make B='$abc'
A=$abc flavour=recursive origin=file
A=$$abc flavour=recursive origin=override
B=$abc flavour=recursive origin=command line
B=$$abc flavour=recursive origin=override
A = $abc
B = $abc
make
make[1]: Entering directory
A=$abc flavour=recursive origin=environment
A=$$abc flavour=recursive origin=override
B=$abc flavour=recursive origin=command line
B=$$abc flavour=recursive origin=override
A = $abc
B = $abc
make[1]: Leaving directory
Try this:
In console:
export HASH='$6$salt$val'; make
in Makefile:
.PHONY: tst
tst:
#echo "$$HASH"
Result:
$6$salt$val
Example:
var1 = x
dep : $(var1)
echo ($^ -> $#)
This will show x -> dep, but what I really want to show is var1 -> dep.
I basically want to sprinkle this echo all over the rules so I can make sense of a dependency graph. Nothing else worked.
Firstly, to work in my environment your makefile needs two slight modifications: replace the parentheses in echo with quotes, and add a rule for x, to give:
var1 = x
dep: $(var1)
echo "$^ -> $#"
x:
There appears to be no method to recover the unexpanded form of a variable name in a recipe. My suggested solution/work-around is twofold: cache the variable name in another variable, and as per MadScientist's comment use $(warning ...). For example, the makefile:
var1 = x
dep: var1_=var1
dep: $(var1)
#echo "$^ -> $#"
#echo "$(var1_) -> $#"
$(warning "Info: Using $^ to build $#")
$(warning "Info: Using $(var1) to build $#")
$(warning "Info: Using $(var1_) to build $#")
$(warning "Info: Using $($(var1_)) to build $#")
x:
will give:
Makefile:7: "Info: Using x to build dep"
Makefile:8: "Info: Using x to build dep"
Makefile:9: "Info: Using var1 to build dep"
Makefile:10: "Info: Using x to build dep"
x -> dep
var1 -> dep
The var1_ variable needs to be defined on a separate line (see https://stackoverflow.com/a/20714468/318716), which doesn't appear to be well-documented. And the order of the output is interesting.
Edit: A more simple variant of this idea is to replace:
var1 = x
dep: var1_=var1
with just:
var1 = x
var1_ = var1
I want to write a call function something like this
define run
#echo "running" > $1
ifeq ("$(var)" "var1")
#echo "var1" > $1
else
#echo "var2" > $1
endif
endef
Problem is I am not able to figure out from make documents how to use ifeq inside a call function, or if there is any better solution than using ifeq.
Putting a conditional in a canned sequence of commands is a pain. It's much easier to resolve the conditional outside:
define run
#echo "running" > $(log)
#echo $(var) > $(log)
endef
targ: log := 23B.log
targ: var := var1
targ:
$(run)
I have something like this in my makefile:
exit_code := $(shell some_script.py; echo $$?)
ifneq ($(exit_code),0)
$(error Error occured)
endif
and it works properly - the echo $$? returns exit code of python script
I need to put that code into define like that:
define run-python-script
exit_code := $(shell some_script.py; echo $$?)
ifneq ($(exit_code),0)
$(error Error occured)
endif
endef
$(call run-python-script)
but then exit_code does not contain the exit code. And $(error Error occured) is always executed.
How to make work the version with define?
I need to put that code into define like that:
The if()/endif are processed and evaluated when the Makefile is parsed. You can't use them inside a variable definition.
The exit_code := ... in first snippet is a definition of a make variable, while in the second it is just a string, part of the make's variable called run-python-script.
You can try this (your script is replaced with false for test purposes):
eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
the-command = false; echo $$?
run-python-script = $(if $(call eq,0,$(shell $(the-command))),,$(error Error occured))
$(run-python-script)
(The $(call) is redundant in that case.)
In Kernel Makefile i found the code like below:
ctags CTAGS CSCOPE: $(HEADERS) $(SOURCES)
$(ETAGS) $(ETAGSFALGS) $(HEADERS) $(SOURCES)
$(call cmd, ctags)
Also, where can i find the Macro or function ?
Using MadScientist's method on kernel v4.1:
make -p | grep -B1 -E '^cmd '
we find:
# makefile (from `scripts/Kbuild.include', line 211)
cmd = #$(echo-cmd) $(cmd_$(1))
scripts/Kbuild.include is included on the top level Makefile. It also contains:
echo-cmd = $(if $($(quiet)cmd_$(1)),\
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
quiet: set at the top level makefile, depending on the value of V.
Will be either:
quiet_ to print CC file.c
empty to print the command on V=
silent_ to not print anything on make -s
escsq is defined as:
squote := '
escsq = $(subst $(squote),'\$(squote)',$1)
It escapes single quotes so that echo '$(call escsq,Letter 'a'.' will print properly in sh.
echo-why: defined further down at Kbuild.include.
It is used for make V=2, and says why a target is being remade.
The setup of make tags is done in the Makefile:
quiet_cmd_tags = GEN $#
cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $#
tags TAGS cscope gtags: FORCE
$(call cmd,tags)
Which shows the typical usage pattern for calling commands on kbuild:
quiet_cmd_XXX = NAME $#
cmd_XXX = actual-command $#
target: prerequisites
$(call cmd,tags)
A comment on the Makefile explains how all of this is done to make the make output prettier:
# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$#
# cmd_cc_o_c = $(CC) $(c_flags) -c -o $# $<
If you run make -p it will print the entire database of all variables, rules, etc. with line numbers where they were last defined.