I have a use case where I need to run the same command multiple times inside a rule. However, the command arguments need to change based on the return value of another command. I found that one can do $(call foo_exec)
to invoke a macro from within a rule, which is great. However, consider the following simplified code:
define foo_exec
@echo $(if $(filter sylvester,$(shell cat cats.txt)),Found Sylvester!,No Sylvester found!)
endef
build:
$(call foo_exec)
@echo sylvester > cats.txt
$(call foo_exec)
If I run make build
, I get the following output:
cat: cats.txt: No such file or directory
cat: cats.txt: No such file or directory
No Sylvester found!
No Sylvester found!
It definitely writes cats.txt
, but, somehow the macro seems to be evaluated only once, before that file is created.
Also, in my real code, it would be beneficial to have variables created in that macro, but I can't seem to get that work either. The following code:
define foo_exec
MESSAGE := $(if $(filter sylvester,$(shell cat cats.txt)),Found Sylvester!,No Sylvester found!)
@echo $(MESSAGE)
endef
build:
$(call foo_exec)
@echo sylvester > cats.txt
$(call foo_exec)
produces this output:
cat: cats.txt: No such file or directory
cat: cats.txt: No such file or directory
MESSAGE := No Sylvester found!
/bin/sh: MESSAGE: command not found
make: *** [build] Error 127
At this point, I'm starting to feel that maybe macros are not the right way to achieve the desired functionality, but I'm not sure how to go about it and avoid duplicating a lot of code. Any suggestions are welcome!
CodePudding user response:
The following works
define foo_exec
@if egrep -s -q sylvester cats.txt; then echo "Found Sylvester"; else echo "No Sylvester found!"; fi
endef
build:
$(call foo_exec)
@echo sylvester > cats.txt
$(call foo_exec)
With this output:
$ make build
No Sylvester found!
Found Sylvester
The problem is that the macros are expanded at the moment the build
recipe is started. Therefore, we don't want the macro expansion to check for the presence of the cats.txt
file. Instead, we want the macro to generate bash code that will do the check
I'm probably not explaining it very well!