Makefile :
-- Makefile --
q_abc :
#echo abc
q_def :
#echo def
q_ghi :
#echo ghi
-- execution --
$make q_abc
abc
$make q_def
def
How can I compact the Makefile?
q_% :
#echo %
doesn't work.
The 'stem' of the pattern (i.e. the bit that matched the '%' wildcard) is represented by $* in the commands part of the recipe. So try something like...
q_%:
#echo $*
Related
up make level could export variable X, and sub-make could use the variable X. is there a way do opposite? I want sub make pass variable to upper level make.
following code won't work.
Makefile
a:
make -f eval_X.mk
echo $(X)
eval_X.mk
b:
$(eval X=123)
Each make target commands run as a sub shell. So there is no existience of variable outside single command. Take a look at this if it helps:
VAR_X = 11
test:
$(eval VAR_X=123)
#echo ${VAR_X} // output : 123
test2:
#echo ${VAR_X} // output : 11
Also, you can use target dependencies to set the var:
a: $(eval X=123)
echo $(X) // output : 123
I'm trying to perform this substitution without any success with the following,
a="/dev/ttyPS1"
b=$(patsubst \"%\",\\\"\"%\\"\",$(a))
c=$(subst \",\\\"\",$(a))
$(info $(a) $(b) $(c))
Output :
$ make
"/dev/ttyPS1" "/dev/ttyPS1" "/dev/ttyPS1"
Desired Output :
$ make
"/dev/ttyPS1" \""/dev/ttyPS1\"" \""/dev/ttyPS1\""
I must be doing something dumb with the escape sequences since it doesn't appear to change at all... I don't have any preference on how I get there (patsubst, subst, or other). Any ideas? Thanks.
You don't need to escape quotes with backslashes in make syntax: quotes are not special to make. Thus your subst of \" never matches because there's no two-character string \" in the string "/dev/ttyPS1".
Try:
a = "/dev/ttyPS1"
b = $(patsubst "%",\""%"\",$(a))
c = $(subst ",\"",$(a))
$(info $(a) $(b) $(c))
I am writing a makefile. In my use case name of variable is stored in another variable. I am trying to evaluate it from function but it is not evaluating correctly.
In the code I want "devinit" to evaluate to UART_init. What is mistake in my code?
VAR=MYDEV
MYDEV_init=UART_init
define create_kernels_c
echo GGGGG $(VAR)
baseinit=$$(echo $(VAR)_init);
$$(eval devinit=\$$baseinit);
echo devinit $$devinit;
endef
all:
#$(call create_kernels_c)
Use variable substitution twice and do not forget about .ONESHELL: (or append ;\<CR> everywhere):
VAR=MYDEV
MYDEV_init=UART_init
define create_kernels_c
echo GGGGG $(VAR)
devinit=$($(VAR)_init)
echo devinit $$devinit
endef
.ONESHELL:
all:
#$(call create_kernels_c)
I have a shell program that takes ages to complete. As written, executing make build takes 4 x 2 seconds to complete because $(value) is computed for each file.
A solution is to declare value a deferred variable by using := instead of =.
Unfortunately this is not a solution either because it slows down the execution of make clean and any other targets by 2 seconds because value is computed for nothing.
value = $(shell sleep 2 && echo 42)
in = a b c d
out = $(addsuffix .out,$(in))
build: $(out)
%.out: %
echo $(value) > $< || [ rm $# -a true ]
init:
touch $(in)
clean:
rm -vf $(out)
How can I set a variable what is assigned only if used, but only computed once ?
Said differently, I would like build to take 2 seconds to complete and clean to be immediate.
I am not interested to a solution that involves conditionals in order to bypass the assignment of value if the target is not build.
An alternative solution would be this. Unfortunately in this case I need to check whether or not the shelve file needs to be regenerated.
value = $(cat shelve)
shelve:
sleep 2 && echo 42 > $# || [ rm $# -a true ]
in = a b c d
out = $(addsuffix .out,$(in))
build: $(out)
%.out: %
echo $(value) > $< || [ rm $# -a true ]
init:
touch $(in)
clean:
rm -vf $(out)
Here's a trick you can play:
value = $(eval value := $(shell cat shelve))$(value)
How this works: value is first assigned using recursive assignment so the value on the RHS is not expanded.
The first time value is expanded the make parser will first run the $(eval ...) which starts up a "new parser" for makefiles. In that parser, the content value := $(cat shelve) is evaluated. Here, value is a simple variable assignment so the RHS is expanded immediately and the $(shell ...) is run and assigned to value.
Remember make doesn't really have a concept of variable scope, so this value is just the same global value variable that we are setting in the outer parser.
Then the eval completes and expands to the empty string, and make continues parsing things. Here it finds the value $(value) and expands that... value now has the result from the eval, not the eval text itself, so that's what will be expanded.
Maybe this will help:
value = $(eval value := $(shell cat shelve))$(value)
Here value contains the string $(eval value := $(shell cat shelve))$(value)
Now you expand it:
%.out: %
echo $(value) > $< ...
Make starts to expand this recipe. It gets to $(value) and sees it needs to expand the variable value: since it's recursive it expands the value:
$(eval value := $(shell cat shelve))$(value)
First it expands the eval, which parses this:
value := $(shell cat shelve)
That sets the value variable as a simply-expanded variable, so the RHS is expanded immediately. Say the results of cat shelve are "foo", so value is now set to foo (and it's marked simply expanded).
That's the end of the eval, so then make starts the next part which is $(value), so it looks up the variable value and discovers it's a simply-expanded variable with the value foo.
One solution would be to turn that value into a regular file target that gets updated only when its prerequisites change. If you insist on rebuilding that target for every build, mark it as phony.
When clean target does not depend on that file, then it won't be rebuilt when you invoke make clean.
In
%.out: %
echo $(value) > $< || [ rm $# -a true ]
echo $(value) > $< updates the prerequisite, whereas make expects it to update the target only. Updating a prerequisite must be done by a separate rule with that prerequisite being the target.
You can make the assignment depend on the target name in $(MAKECMDGOALS):
ifneq ($(MAKECMDGOALS),clean)
value := $(shell sleep 2 && echo 42)
endif
See also the docs for details.
I'm wondering if it's possible to override a target in a makefile! The environment I'm working in does not allow me to do this due to auto generation! I was wondering if I coded the same rule above or below the static target would this achieve an override?
%_emul.flist: $(if ${GEN_FLIST},%_synth.flist,) ${rdlh_file_deps}
${QUIET}if test ${SYN_DEBUG} -eq 1 ; then set -xv ; fi; \
$(if ${TOOL_VERILOG},rm -f $#; touch $#,$(if ${TOOL_BBOX_LIBS},echo ${TOOL_BBOX_LIBS} > $#,rm -f $#; touch $#))
/bin/sed -e '/\/libs\//d' -e '/\/place\//d' $(foreach mod,$(filter %.vhd,$^),-e 's%^\(.*\/\)\{0,1\}$(basename $(notdir ${mod}))\.v$$%${mod}%') $*_synth.flist >> $#
Yes , i think that would work .... but you need to be a bit more careful in the way you code things. You don't want to override something that might be useful!
GNU make would take the most recent of the target it encounters. So, the following works (but not as i would have liked it to work :( )
Output: I think you are looking for something like this --
Kaizen ~/make_prac $ make -nf mk.name
mk.name:20: warning: overriding recipe for target `name'
mk.name:17: warning: ignoring old recipe for target `name'
arg1="Kaizen" ;
echo "hello "" ;" ;
hello ;
Code: Here the target "name" appears twice and is overridden.
Kaizen ~/make_prac $ cat mk.name
##
## make to accept name and display hello name
##
arg1="" ;
.PHONY : name \
hello
#.DEFAULT :
# hello
hello : name
+ echo "hello $(arg1)" ;
name :
echo "name given is : $(arg1)" ;
name :
arg1="Kaizen" ;
PS: Take note of the use of : -- if you use :: then both rules get executed.
Explanation for the arg1 .... not showing in the output: The variable arg1, even though it gets assigned in the first parsing, it gets ignored, since its assignment is target dependent. If you would have had a variable declaration elsewhere -- e.g. like arg1 is defined at the start -- there would not be any dereferencing issues.